過去の記事を一覧で見る

HouseTect, JavaScriptな情報をあなたに

はじめてのiPhoneアプリ - カメラアプリを作る際にハマったことのメモ

とにかく情報はStackOverFlowたよりです。
なので必然的に、ググるときのキーワードも英語になっていきます。

Webに比べるとあまりにもまだまだiPhoneアプリの解説や資料は少ないので、以下の記事がどなたかの助けになれば幸いです。

AppCodeというIDEを使ってみる

appcode.png

JetBrains AppCode: an Objective-C IDE That Makes a Difference

もう、これはすごかった。
さすが1万もするアプリだなーという感じです。

XCodeでもAppCodeと同じようなことができるんだとは思いますが、あまりにも直感的に使えるIDEなので、これがないと厳しいです。
地味ですがダブルコートを打つと自動的に@が補完されるのとか助かります。

あとはコードフォーマッター、どうもXCodeにはないらしいので、これはかなり重宝しました。
リファクタリングもすごくいいです。

gitとも連携できるので、ファイルのヒストリーも見れます。
あとはもう触ればとりこですよ。

ただ一点だけ、
imageView.contentMode =
こう打ったら、この右側で補完されるものはcontentModeで絞り込んで欲しい。
すごいいっぱい出てくるから、毎回ググッて貼り付けてます。

あとは、
2011-12-11 - 人工無脳が作りたい
こちらを読むとさらに使いたくなります。

gitにも対応していてdiffをしてくれるので比較も便利!


AppCodeのカラースキーマをMonokaiにする

以下がカラースキーマの置き場所。
ここにxmlファイルを配置して、PreferencesのColorから選べばOK!

~/Library/Preferences/appCode10/colors/

WebStormで使っていたMonokaiテーマだと、うまくObjective-Cのカラーリングがされなかったので、

hezi/monokai-appcode

こちらを使ってみた。すごく良い感じ。


XCodeのアシスタントエディターがうまく機能しない

アシスタントエディターを使うと、画面がセパレートされ、.hファイルと.mファイルを同時にみたり、
storyboardとそれに紐付くControllerファイルを見ることができますが、これがたま〜〜に機能しなくなるときがあります。

具体的にはstoryboardで選択したViewとそれに設定しているCustomClassのViewControllerが開かない現象です。

これは、何回かXCodeを再起動すれば紐付くようになりました。
とくにstoryboardに配置するViewControllerの量が増えてくるとこの現象が発生するような気がします。

何が原因かはまだ不明。


Objective-Cでシングルトン

Objective-C でシングルトンパターン | Sun Limited Mt.
こちらの記事を参考に書いてみました。

■gist
Objective-Cでシングルトン -- Gist

使い方は、

プロパティの場合はこんな感じですね。


UILabelにPaddingを入れたい

UILabel のテキストのmargin やらpadding やらを設定して表示位置を調整する - laiso - iPhoneアプリ開発グループ
に書かれている方法でバッチリでした。

■gist
UILabelにPadding入れる -- Gist


画像をリサイズしたい

写真アプリなら必ずやりたくなる処理。
必要な分はメソッド化しておきました。

■gist
Objective-Cで画像のリサイズ系 -- Gist

こう書いてみたものので、画像まわりでハマったので、メモしておきます。
UIImageViewのサイズは320だとしても、その中に収める画像UIImageのサイズは640にしないとretinaでぼやけます。
はじめ分からなくて両方に320を指定していたのですが、ぼやけてしまってハマりました。

UIImageViewのリサイズコードは以下の感じです。

そしてさらに、imageView.contentMode = UIViewContentModeScaleToFillにします。
これでInstagramなどと同じようにキレイな画像が出るようになりました。
おー!


UILabelにセットした文字列が長い場合にfontが自動で小さくなるのを防ぐ

XCodeのAutoshrinkのチェックを外す。
或いは、UILabelをプログラムからViewにaddする。


カメラ機能の実装

今回の主人公であるカメラ部分の実装になります。
はじめ、ダレもがやるUIImagePickerControllerを使った実装をしていたのですが、どうもInstagramやPathと違う、何かが違う...
となりまして、いろいろ調べてみると、AVCaptureDeviceクラスを使うとそれっぽいことが可能になると。
(なんだかややこしそう...)

ざっくりデザインを無視して、

  1. カメラが撮れる
  2. アルバムから選べる
  3. 前面カメラを選べる
  4. Flashを切り替えられる
  5. フォーカスできる
  6. 閉じるボタンがある

これらの機能をシンプルに1個のViewControllerで実装してみました。
カメラを撮ると画面右下にちっちゃく表示するようにしています。

あとは確認画面に行ってフィルター掛けてもいいし、ゴニョゴニョしてもいいし。

意外と日本語のサイトでも海外でもそうですが、シンプルにまとまって一つのプロジェクトになっているのがなかったので、
今後これをもとにいろいろ遊んでみようと思います。

■github
hisasann/AVCaptureDeviceCamera


絵文字をMySQLに入れる方法

MySQLで4バイトのUTF-8文字を扱ってみる - HHeLiBeXの日記 正道編

utf8mb4にするというお話


カメラのフラッシュのオートが効かない

はじめ以下のようにtouchModeAVCaptureTorchModeAutoを指定していたんですが、
暗いところで撮影してもいっこうにフラッシュがつかなくてハマっってしまいました。

実際にはflashModeAVCaptureFlashModeAutoを入れるとうまいこと行きました。

たしかにトーチじゃないよな。


iOSで使えるFilterの種類が知りたい!

出力結果:

properties - (
CIAdditionCompositing,
CIAffineTransform,
CICheckerboardGenerator,
CIColorBlendMode,
CIColorBurnBlendMode,
CIColorControls,
CIColorCube,
CIColorDodgeBlendMode,
CIColorInvert,
CIColorMatrix,
CIColorMonochrome,
CIConstantColorGenerator,
CICrop,
CIDarkenBlendMode,
CIDifferenceBlendMode,
CIExclusionBlendMode,
CIExposureAdjust,
CIFalseColor,
CIGammaAdjust,
CIGaussianGradient,
CIHardLightBlendMode,
CIHighlightShadowAdjust,
CIHueAdjust,
CIHueBlendMode,
CILightenBlendMode,
CILinearGradient,
CILuminosityBlendMode,
CIMaximumCompositing,
CIMinimumCompositing,
CIMultiplyBlendMode,
CIMultiplyCompositing,
CIOverlayBlendMode,
CIRadialGradient,
CISaturationBlendMode,
CIScreenBlendMode,
CISepiaTone,
CISoftLightBlendMode,
CISourceAtopCompositing,
CISourceInCompositing,
CISourceOutCompositing,
CISourceOverCompositing,
CIStraightenFilter,
CIStripesGenerator,
CITemperatureAndTint,
CIToneCurve,
CIVibrance,
CIVignette,
CIWhitePointAdjust
)

[via]
iphone - CIColorPosterize in iOS - Stack Overflow

フィルターはこれから実装するのですが、
『第3回 iphone_dev_jp 東京iPhone/Mac勉強会』で vImage について発表してきました - Over&Out その後
こちらを見て、vImage vs CoreImage vs OpenCV といろいろやり方があるのが分かりました。
この道もそれはそれは大変そうです。


UIImageViewにUITapGestureRecognizerをセットしてもイベントが発生しない

UIImageViewに設定したGestureイベントが発生しない - 日々精進
こちらの記事のとおりなんですが、

こんな感じでUIImageViewにUITapGestureRecognizerをセットしても、イベントが発生しない。
これはUIImageViewのuserInteractionEnabledをYESにすれば発生するようになります。


メモリ不足によりviewDidUnloadが呼ばれた場合に状態を復元する方法

Cocoaの日々: UIViewController - 状態保存復元パターン

今回、とってもハマったのが、このviewDidUnloadだ。

落ちないiPhoneアプリが作りたい自分のための、押さえておくべきポイントたくさん。 - かってぃのブログ | choilog [チョイログ]
【iPhone】メモリ不足時のシミュレートとデバッグ | iPhoneアプリで稼げるのか
2009-01-21 - f-shinの日記 - iPhoneアプリ開発グループ
iPhoneアプリ開発まっしぐら★ - iPhoneアプリ開発グループ
Safx: ViewControllerにおけるビュー管理サイクルとメモリ警告シミュレーションによるアンロード処理について
このあたりをよく読むと理解できるか、今回発生した現象はあまりググっても出て来なかったのでここにメモしておきます。

今回使ったPathライクなUIライブラリはECSlidingViewControllerですが、
これは最上位となるViewControllerがいて、それが実際のECSlidingViewControllerになります。

つまり、

  • ViewController
  • TopViewController

の2つがいて、ViewControllerはECSlidingViewControllerをインプリメントしているだけ、
本当のトップViewはTopViewControllerになります。

TopViewControllerにあるUITableViewをタップするとサムネイル画面に遷移する仕様なので、
ThumbnailViewControllerとしときましょう。

このThumbnailViewController画面でカメラをModalで開きます。
(下からニュルっと出てきます)

こんな感じのコードです。
よくあるコードですね。

このCameraViewControllerを開くまでに、画像を結構表示しているとして、viewDidUnloadが発生しやすい状態にしておきます。(またはシミュレータででメモリワーニングを出す)
そして、CameraViewControllerをModalで開いてTumbnailViewControllerのviewDidUnloadが発生し、CameraViewControllerを閉じたときに画面が真っ白になってしまう現象が発生しました。
ここが真っ白になってしまうは、ECSlidingViewControllerの影響かもしれません。

いろいろな解説記事を読むと、viewDidUnload後にビューが表示されるタイミングでもう一度viewDidLoadが発生すると書かれているんですが、これが発生しませんでした。

結論を言うと最も親であるViewControllerもviewDidUnloadされてしまっていました。

これにより、TumbnailViewController意外のTopViewControllerやViewControllerもなくなってしまっていたので、真っ白の画面になってしまいました。
そこでViewControllerのviewDidUnloadが発生したタイミングでTumbnailViewControllerまでを復元するようにするコードを書きました。

つまり、メモリワーニングでModal以外のViewが破棄されても、Modalが閉じられて後ろ側が見えるようになる瞬間で、

  • ViewControllerのviewDidLoadが呼び出される
  • TopViewControllerを復元
  • ThumbnailViewControllerを復元
  • サムネイル画面があたかもずうっとあったかのように見せる。

こうなりました。(ややこしい!)

ちなみに、ModalではなくNavigationでやった場合、同じようにメモリワーニングが起こると、TopViewControllerまで強制的に戻される動作をするので、あまりにも不自然な動作ゆえにやめました。

iPhoneアプリはメモリまわりがかなり難しいですが、viewDidUnloadもこれまた難しい。
以下に、真っ白にはならないのですが、メモリワーニング後に適切な画面が表示されないパターンを作ってみました。
参考までに。

■github
hisasann/ModalDidReceiveMemoryWarning


UIImagePickerControllerでフォトライブラリーを開いたときのナビゲーションバーの色を変えたい

navigationBar.tintColorにUIColorを入れると変えられるようです。


PullToRefreshしたい!

sonnyparlin/PullToRefresh
これを使えばほんとうに簡単に実現できました。

サンプルのプロジェクトを作成したのでこちらを参考にしてみてください。

■ArcPullToRefresh
hisasann/ArcPullToRefresh

だいたい以下のようなコードを追加するだけになります。


自分のアプリのメモリ使用量をアプリ内で知る方法

こんな感じ。

[via]
自分のアプリが使用しているメモリサイズを取得するには - The iPhone Development Playground


データを保存する場所について

ディレクトリいろいろ。

/アプリ名.app
メインバンドルと呼ばれている。アプリのリソースファイルを保存するためのディレクトリ。読み取り専用。

/Documents
アプリがファイルを作成して保存することができるディレクトリ。永続化したデータを格納する場合ここを使うのが一般的

/Library/Caches
アプリが一時的に使う情報を保存するディレクトリ

/Library/Preferences
アプリケーションの設定を保存するディレクトリ。NSUserDefaults のデータが保存される

/tmp
一時ファイルを保存するディレクトリ。アプリが動作してないときに消される可能性がある

[via]
iOS でデータを永続化する方法 - A Day In The Life

パスの取得いろいろ。

NSHomeDirectory()
/var/mobile/Applications/FBAD8D21-CFFC-4804-85AC-7F6F02DCB836

NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
/var/mobile/Applications/FBAD8D21-CFFC-4804-85AC-7F6F02DCB836/Documents

NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)
/var/mobile/Applications/FBAD8D21-CFFC-4804-85AC-7F6F02DCB836/Library

NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
/var/mobile/Applications/FBAD8D21-CFFC-4804-85AC-7F6F02DCB836/Library/Caches

NSTemporaryDirectory()
/private/var/mobile/Applications/FBAD8D21-CFFC-4804-85AC-7F6F02DCB836/tmp/

[via]
アプリのsandboxをURLを取り出す - iPhoneアプリケーション開発


Exif情報を付与する - これは苦労しました...

もうこれはとにかくハマりました。
Exifなどのメタデータを自由に操作するにはどうするか - AppStair
JPEGファイルのExif情報を読み書きする - 強火で進め
無題メモランダム: [iOS]画像にEXIFなどのメタデータを付加する方法メモ
[AssetsLibrary] フォトライブラリの写真にExif情報を付けて保存する - Ni chicha, ni limona - 平均から抜けられない僕 - iPhoneアプリ開発グループ
このあたりのすばらしい記事を読んでいろいろ試してみたんですが、どうしてもサーバーに画像をPostするとExifが入らない現象に悩まされました。

結果的に、PostするときにUIImageからNSDataに変換していたんですが、ここでExif情報を抜け落ちているのが分かりました。
こんなコードです。

これをやってしまうと、Exifが抜け落ちてしまう...
以下に2種類のExif付与の方法を書いておきます。

  1. 画像ファイルは作らずにNSDataを作る方法
  2. 画像ファイルを作る方法

たとえば、Exifを付与した画像ファイルを、また別のViewでも使いたい場合など、ファイルに保存しておくと良いかもしれません。

Exifを付与しNSDataを作成するサンプルコード

以下のコードでは、

  • kCGImagePropertyExifDateTimeOriginal
  • kCGImagePropertyExifDateTimeDigitized

の2つのExif情報を付与しています。

■gist
Exifを付与しNSDataを作成するサンプルコード -- Gist

Exifを付与し、/tmpに画像を保存するサンプルコード

以下のコードでは、


  • kCGImagePropertyExifDateTimeOriginal

  • kCGImagePropertyExifDateTimeDigitized

  • の2つのExif情報を付与しています。

    ■gist
    Exifを付与し、/tmpに画像を保存するサンプルコード -- Gist

    そして、これをサーバーにPostする際に

    のようにしてdataを作りこれをPostしています。
    ちなみにExifを抜き出す作業はそこそこメモリ資料率が上昇します。
    これはどうも画像サイズが大きければ大きいほど上昇するようです。なので、小さいサイズにしたUIImageから抜くとかすると抑えられる感じです。

    ■参考リンク
    Exif TAG

    フォトライブラリーから選んだ画像のExifから撮影日を取得したい

    これもたいそうハマったんですが、
    UIImagePickerControllerのsourceTypeにUIImagePickerControllerSourceTypePhotoLibraryを指定してフォトライブラリー画面を出し、そこから写真を選ぶと

    こんなメソッドが呼ばれます。

    このときにUIImagePickerControllerのallowsEditingをNOにしていると、Exif情報を持っているはずのeditingInfoがnilになってしまいます。

    YESにするとExifが入った状態になります。

    [via]
    [iOS][Objective-C]カメラを使ってみようの巻 | なんだかんだ言って甘いもの好きでしょ?日記

    UIImagePickerControllerでイメージピッカーからExif情報を抜き出す

    ALAssetsLibraryを使う以下の方法で落ち着きました。

    ■gist
    UIImagePickerControllerでイメージピッカーからExif情報を抜き出す -- Gist

    [via]
    UIImagePickerController経由でカメラロールの写真のExifにアクセスしたいねん | Eudyptes Chrysocome

    このメソッドの引数のimageのサイズは以下。(iPhone4の場合)

    image.size.width - 640.000000
    image.size.height - 640.000000

    editingInfoから抜き出したeditedImageのサイズは以下。

    editedImage.size.width - 0.000000
    editedImage.size.height - 0.000000

    editingInfoから抜き出したoriginalImageのサイズは以下。(つまりもとの画像サイズ)

    originalImage.size.width - 1434.000000
    originalImage.size.height - 1920.000000

    [via]
    iphone - UIImagePickerController allowsEditing=YES Issue - Stack Overflow

    位置情報へのアクセスを許可していない場合に、ALAssetsLibraryからフォトライブラリーにアクセスすると出るエラー

    どうもALAssetsLibraryを使ってExifを抜き出すコードがあると?、位置情報を取得しても大丈夫ですか的なダイアログで出るんですが、そこでいいえを選択するか、はいにはしたけどあとからシステム環境設定でいいえにした場合に、ALAssetsLibraryのfailureBlockに入ってしまうようです。

    2012-08-01 18:32:48.531 HogeAPP[15197:707] error - Error Domain=ALAssetsLibraryErrorDomain Code=-3311 "User denied access" UserInfo=0x2c81e0 {NSLocalizedFailureReason=The user has denied the application access to their media., NSUnderlyingError=0xceae140 "The operation couldn't be completed. (PersistentURLTranslator error 1.)", NSLocalizedDescription=User denied access}

    はじめ原因が分からなかったんですが、よくよく自分がやったことを思い出したら許可しないにしたなーと。

    iPhoneアプリ開発塾
    iPhoneアプリ開発塾
    posted with amazlet at 12.09.11
    カワサキ タカシ
    技術評論社
    売り上げランキング: 1998

    DataPickerを下からニュルっと!

    [iPhone] 下からニュッと出てくるDatePicker | BuGcloUd.com
    こちらの記事を参考に作りました。

    でも、DatePickerって出現すると10MBぐらいメモリ使用量があがるんですね。


    縦長のUIScrollViewをstoryboard上でデザインしたい!

    iPhone画面サイズを超えるViewをStoryBoardに配置する方法について - Google グループ
    こちらで議論されていますが、結果的にぼくも便乗して、
    StoryBoard&スクロールビューで画面サイズ調整 - Object for cutie
    この方法でやってみることにしました。

    つまり、

    「親となるViewControllerがあり、その中にContentSizeの高さが長いstoryboard上でデザインしたUIScrollViewを配置することができるようになる。」

    ということになります。

    たとえば、入力→確認という画面遷移を考えたときに、
    入力画面の項目が多ければ、460pxの中には収まりません。
    そうするとデザインが目で確認しながらではなく、プログラムから行う必要が出てきてしまうので、この方法で助けられました。

    ただし、親のUIViewControllerで、

    のようにする必要があるので、不必要なUIViewControllerのインスタンスが生成されているかもしれません。
    とはいえ、メモリを監視しているとそこまで上がらないので大丈夫だと思われます。


    RGBをUIColorとして使いたい

    これは僕が知らないだけかもしれませんが、XCode上の色を選ぶことができるColorsビューにて、
    Web Safe Colorsのところで指定したい16進を入力しても、ないみたいに言われて指定できないので
    プログラムから行うことにしました。

    16進数から10進数のRGBに変換は以下のサイトがいいです。
    もうここに助けられた!
    RGB変換 (16進数→10進数) (16進数→10進数)

    こんな感じで使います。


    UITextViewをタップしたい!

    覚え書き☆iPhoneプログラミング UITextViewでタップイベント
    こちらのとおり、カスタムなUITextViewなクラスを作って、touchesBeganに処理を書くようにしました。

    これはUITextViewをタップしたときにDatePickerを表示するときに使いました。
    ちなみに、DatePickerって表示すると10MB近くメモリが上昇するんですが、結構重いんですね。


    UITextFieldをタップしたときにキーボードの下に隠れないようにする

    iPhone SDKで、コンテンツがキーボードで隠れないようにする。 - このブログは証明できない。
    TextFieldにテキストを入力したとき画面の下が隠れてしまわないようにする方法 - ガジェット充まゆたまのiPhone開発知恵袋
    こちらの記事を参考にさせていただきました。

    そして最終的なコードが以下。

    とその前に、現在アクティブなUITextFieldを取得するために
    iPhone SDKで、アクティブな(フォーカスのある)UITextFieldを取得するには? - このブログは証明できない。
    こちらのコードも参考にさせていただいた。

    サンプルコード

    ■gist
    UITextFieldをタップしたときにキーボードの下に隠れないようにする -- Gist

    ちなみにですが、UITextViewの場合は、かってにフォーカス?するので、あえてここでUITextViewの表示位置にスクロールするということはしていないです。
    あと、いろいろ検索して見つけたコードを試してみたところ、上記のパターンじゃない方法(忘れちゃいました)で書かれたコードを使うと、UITextFieldをタップしてもアクティブにならない現象が発生しました。
    何度かタップするとアクティブになるんですが、その挙動がいやで、上記のパターンでは起こらなかったのでこちらを採用しております。


    UINavigationControllerを指定したView、または一番初めのViewに戻したい

    UINavigationControllerを2ページ目に戻す方法

    UINavigationControllerを最初のページに戻す方法

    [via]
    UINavigationControllerを使って、指定したビューまで戻ってメソッドも実行する|成長の果実

    もどると、ちゃんとdeallocも呼ばれます。


    複数開いたモーダルビューを一気に閉じたい!

    モーダルビューをすべて閉じる方法を教えてください « 寺子屋サルでき旧館 | iPhoneアプリ開発をもっともっと楽しく!困ったらみんなで解決!
    presentModalViewControllerで表示した2階層以上の画面から一気に戻る方法 - Faith and Brave - C++で遊ぼう

    これなかなか難しいですね。
    そもそもiOS5からなのか、viewWillAppear時に[self dismissModalViewControllerAnimated:YES];を呼んでも消えてくれなくて、
    viewDidAppearなら消えてくれます。

    なので、一気に消えるというよりは、パラパラと消えていくという感じになってしまいました。
    そこでぼくは、

    1. 親となる画面から1つ目の子画面を開く
    2. 1つ目の子画面から2つ目の子画面を開くんだが、その命令は親画面に移譲する
    3. 親画面が1つ目の画面を消して2つ目の子画面を開く
    4. 2つ目の子画面から1つ目の子画面に戻るときも同じように親画面に移譲する
    5. 2つ目の画面を閉じると1枚しか開いていないので、あたかも2枚閉じたように見える

    この挙動は、カメラを撮る→確認画面に行く→(ナビゲーション)→投稿画面に行くというInstagramの挙動と同じ感じかなーと思っています。

    親画面のサンプルコード

    1つ目の子画面のサンプルコード

    2つ目の子画面のサンプルコード

    こんな感じです。
    ここに行き着くまでに結構ハマりましたね。

    ※この方法は最終的に使いませんでした。
    とくにモーダルを開くシーンで使うのですが、メモリワーニングなイベントが起きた場合に親のViewControllerが破棄されると、2つ目の画面への遷移が親からなので、遷移できなくなるためです。
    なので、一気に2枚のViewを閉じる画面はなくしました。


    Could not find a storyboard named 'iPhone' in bundle NSBundleが出る場合

    なんでか不明ですが、storyboardがうまくロードされない場合がある。
    それは、誰かにプロジェクトを渡して、その人のXCodeでビルドしたときに起こりました。

    2012-08-03 13:29:13.804 HogeAPP[1403:1a303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'iPhone' in bundle NSBundle (loaded)'
    *** First throw call stack:
    (0x1d09022 0x1979cd6 0xf069f2 0xadbd60 0xadbff8 0xadb17f 0xaea183 0xaeac38 0xade634 0x26c3ef5 0x1cdd195 0x1c41ff2 0x1c408da 0x1c3fd84 0x1c3fc9b 0xadac65 0xadc626 0x24cd 0x2435)
    terminate called throwing an exception

    解決策は以下の通りで、いったんstoryboardの参照を削除して、Finderからもう一度XCode上にドラッグしてあげる。
    これでビルド時に上記エラーがでなくなりました。

    1. Right-click on your MainStoryboard.storyboard in the Project Navigator.

    2. Select Delete and click Remove References Only.

    3. Right click on InfoPlist.strings and select "Show In Finder". (This is just my lazy way to open the folder containing the storyboard in finder.)

    4. Drag the MainStoryboard.storyboard from Finder back into the project.

    via: ios - XCode 4.2 MainStoryBoard Not Found - Stack Overflow

    [via]
    ios - XCode 4.2 MainStoryBoard Not Found - Stack Overflow


    メモリリーク箇所を発見する、そして循環参照をなくす!

    これはそれはそれは大変な作業です。

    静的アナライザ

    メニューバーの「Product→Analyze」よりXCodeに発見してもらう。
    ただし、以下のようにあくまでも補助として使うほうがよさそうです。

    Clang Static Analyzer を使うとメモリリーク箇所を解析して教えてくれます。完璧じゃないので油断は禁物ですけど。ちなみに Xcode3.2 からは標準で Clang Static Analyzer が組み込まれています。Build > Build and Analyze で解析できます。


    via: iPhoneアプリ開発時のメモリ管理で気をつけること - A Day In The Life

    ■参考リンク
    iPhoneアプリ開発時のメモリ管理で気をつけること - A Day In The Life

    Instruments

    InstrumentsUserGuide.pdfを読みながらがんばっているが、やはりInstrumentsの使い方はなかなか難しい。

    特にActivitiMonitorのReal Memがどれぐらいリアルなのかが気になるw
    聞いた情報だと、開放されたメモリもここに表示されている?とかで、結構なメモリ量になっている。

    Instruments.png

    だいたいアプリ起動時は8MBほどで、いろいろなViewやコントロールを開くとどんどん上がっていく。
    このどんどん上がっていくViewControllerにdeallocのメソッドを書いて、本当に開放されているかをチェックしてみたら、これまた開放されていない箇所が盛りだくさんだった。

    また、ActivitiMonitorではなくAllocationsでメモリ状態を監視した場合の各列の意味は、
    Instruments の Leaks の見方(Live Bytes や Living の意味) - Over&Out その後
    こちらに詳しく書かれていました。

    Live Bytes



    The Live Bytes column indicates how many of this type of object have been allocated and still are around in memory.


    該当するタイプのオブジェクトの現在のメモリ使用量

    via: Instruments の Leaks の見方(Live Bytes や Living の意味) - Over&Out その後

    こちらが実メモリということなんですかね。
    でもActivitiMonitorでは起動時8MBぐらいだったのが、こちらでは1MBほどになっている。
    ここはまた別で調査しないと。

    循環参照なサンプルコード

    たとえば、UIViewController内で何かLogicを呼び出し、このコールバックとしてさらに何かを実行した場合、
    自分自身を表すselfをブロック内に渡したくなる。

    ただし、これだと

    • UIViewControllerがLogicの参照
    • Logicがselfを通じてUIViewControllerを参照

    という循環参照が発生してしまう。
    最悪、deallocが呼ばれずにメモリ開放されなくなってしまう。

    循環参照しないサンプルコード

    まるでJavaScriptのようなコードだが、これで循環参照を防ぐことができます。

    __weakで弱い参照状態にして、あくまでも参照カウンターは上げないのがポイントです。

    ブロック内にselfを渡したり、インスタンス変数を渡したりするとメモリが開放されないということを知るまでに結構な時間を費やしました。
    この作業を地道に行なっていったところ、目的のほぼすべてのViewControllerでdeallocが呼ばれ、Real Memも増えるけど下がるという状態にまでもって行けました。

    余談ですが、facebookもinstagramも50MBを超える量のメモリをガンガン使っているので、最終的にメモリが開放された時点で50MB以下になっていればいいのかなーなんて思いました。

    ■参考リンク
    メモリリークを調べたい - ちくわプログラマにっき
    Instruments の Leaks の見方(Live Bytes や Living の意味) - Over&Out その後
    deallocが呼ばれない - てきとーブログ


    InstagramやTweetbotのようなカスタムなタブにしたい!

    【iPhone】任意のデザインにタブバーをカスタマイズする - 坊やがゆく
    こちらの記事の、
    PoohKid/FreeDesignedTabBar2 · GitHub
    この方法がすばらしいです。

    このカスタムタブの方法も地味〜にあんまりネットになかったりするので、助かりました。
    すべてのタブを画像にするなど、本当に独自にやりたい場合にこれで行けます。


    同時タップによる多重遷移のエラーに対処する

    指2本で複数のオブジェクトを一緒にタップする場合になります。

    Modalを複数開いてしまうケースのエラー

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active

    UITableViewで複数のCellをタップした場合のエラー

    Unbalanced calls to begin/end appearance transitions

    回避サンプルコード

    かなり力技ではあるが、以下のようにフラグを設けて、すでにオープンしている場合はそれ以降の呼び出しを無効にする。

    今回はUITapGestureRecognizerを使って、画像たちにModalを開くイベントをセットしていたので、このような同時タップで
    イベント自体が2回走ってしまい、2回目のModalOpenでエラーになってしまう。

    こうゆうことにも配慮が必要なのだとすごく勉強になったエラーでした。


    ライブラリを追加したときにエラーになる場合

    以下のようなエラーが出る場合がある。
    これはライブラリをプロジェクトに追加したんだが、XCodeの「Target Membership」に追加していないときに発生する。

    Undefined symbols for architecture armv7:
    "_OBJC_CLASS_$_Stats", referenced from:
    objc-class-ref in AppDelegate.o
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    ライブラリの.mファイルを選択し、XCode上から追加してあげよう。
    ライブラリでなくても普通にViewControllerのクラスを追加したときに、別のターゲットにチェックを付けていないと同じ現象は発生する。


    リジェクトされたくないので一読

    iPhoneアプリ審査での111の禁止項目(意訳) | fladdict


    各種アイコンのサイズ

    [iOS] アプリに必要なアイコン・起動画面の画像サイズ&ファイル名 | tande lab.

    使ったライブラリ

    R9HTTPRequest

    HTTP通信を簡単にしてくれたライブラリで、国産ということもあり、すごく馴染みやすかったです。
    非同期でブロックをコールバックに渡すスタイルなので、JavaScriptっぽくて使ってみました。

    iPhoneアプリ開発がはじめてだったので、このライブラリにはほんと助けられました。

    一点、画像をPostする際にメモリリークしている箇所があったので、nilを入れるように修正しました。

    pull requestした。
    Pull Request #1: 画像Post時のメモリリーク解消 by hisasann · glassonion1/R9HTTPRequest

    ■ダウンロード
    glassonion1/R9HTTPRequest

    ■解説
    シンプルで簡単に HTTP 通信が出来るライブラリを公開しました - A Day In The Life

    この後、結局のところ通信のタイムアウトがR9HTTPRequestだと240秒以下にできない問題があったので、ASIHTTPRequestに乗り換えました。
    どうもこれがデファクト?っぽい感じだったので。
    あかばね式 [iPhone]POSTする場合のタイムアウト設定値が無視される(場合がある)件

    R9HTTPRequestとほぼ同じようなコードなので、乗り換えはかなり簡単でした。
    ただしASIHTTPRequestはARCに対応していないので、
    ARCを有効にしたプロジェクトでASIHTTPRequestを使用する|成長の果実
    こちらで紹介されている、「-fno-objc-arc」を記述する必要があります。

    もう開発が止まっているライブラリですが、これはなかなかよいです。

    ■リンク
    ASIHTTPRequest Documentation - All-Seeing Interactive

    ECSlidingViewController

    PathなUIを実現する必要があって、でも自分で一からは厳しいなと思っていて、
    Facebookアプリを真似たメニュー機能を実現「ECSlidingViewController」 - MOONGIFT|オープンソース・ソフトウェア紹介を軸としたITエンジニア、Webデザイナー向けブログ
    こちらの記事を読んで採用してみました。

    実際には、導入もすごく楽で、スムーズだし、これもまたすばらしいライブラリでした。
    おそらくPathライクなUI用のライブラリとしては、だんとつ人気なんじゃないでしょうか

    ■ダウンロード
    edgecase/ECSlidingViewController

    MBProgressHUD

    比較的よく使われているLoadingレイヤーを出すライブラリです。
    なかなか海外でも評価が高いので、採用してみたのですが、少し使い方に注意が必要でした。

    Demoのコードを見てみると、以下の様にバンバンaddSubviewしているんですが、

    これはviewを渡しているかなのかわかりませんが、dealloc後にも開放されずに残ってしまうようでした。
    そして、Demoをよく見てみたら、こんなコードをimplementしていて、ここでremoveしていました。

    ただこのコードはLoadingの表示が終わったら呼ばれるようなので、それだとLoadingを出すたびにインスタンスが作られるので、

    ぼくは、viewWillAppearで追加して、viewWillDisappearでremoveするようにしました。
    これでメモリは開放されます。

    これでLoadingを出すときにメッセージも渡しつつshowする感じになります。

    ■ダウンロード
    jdg/MBProgressHUD

    SBJson

    Objective-Cではこれ!というぐらい調べていくとこのライブラリになりました。
    JSON用のライブラリです。

    とくに問題なく使えました。

    ■ダウンロード
    SBJson

    Underscore

    まさかのUnderscore.jsのUnderscore.m版がありました。
    でもwhithoutしか使いませんでしたw

    ■ダウンロード
    Underscore.m

    [via]
    iPhoneアプリ開発で使えるObjective-Cライブラリの紹介 | SmartAppsCreative

    このUnderscoreの面白いところは、[obj hoge]のように本来ならブラケットで囲われるのが普通だが、丸括弧で呼び出す方法を提供している。
    それの解説ではないが、小さくまとめたものをgithubのほうに上げておきました。

    ■github
    hisasann/Objective-CnoSquareBracketMethodCall


    スマホアプリのデザインをいっぱい見たい!

    Recent / iOS UI Patterns (beta)
    もうここのサイトが本当に参考になります。
    比較的有名なアプリの画面が、画面のジャンルごとにわかれているのでとっても見やすい。


    読み物

    iPhoneアプリで食べていく――「ぐんまのやぼう」ができるまで (1/3) - ITmedia ニュース


    まとめ

    今回、あまりまわりに聞ける人がいない環境で、頼れるのはグーグルさんだけだったのですが、けっこうたいへんでした。
    とくにググっても有力な情報が出てこないばかりか、XCodeが古い時代の記事はそもそも間違っていたりと玉石混交過ぎました。

    なので、とにかく実験、実験を重ねて、なんとかつかむことができましたが。

    ほんと、こうゆうハマる作業が好きなのはプログラマーゆえですよね。

    ハマってなんぼ!

    どうもありがとうございました!


    今回読んだ本

    よくわかるiPhoneアプリ開発の教科書【iOS 5&Xcode 4.2対応版】
    森巧尚
    マイナビ
    売り上げランキング: 1615

    この本はほんと初歩の初歩ですが、それすらも分からなかったので、まずはこれをざっくりやってstoryboardの感触を掴みました。

    詳解 Objective-C 2.0 第3版
    荻原 剛志
    ソフトバンククリエイティブ
    売り上げランキング: 2386

    この本はすごい!
    けど、なかなかなハードルであります。気長に読んでいこうかと。

    書評 - jQuery Mobile パーフェクトガイド

    • 2012-08-28 (火)

    Impress Japan社より献本いただきました。
    ありがとうございます!

    jQuery Mobileを徹底解説!
    基礎から分かる。現場でも活用できる。


    □ □ □ □ □
    jQuery Mobileを使ったサイト制作の基本から実践までを網羅的に解説。

    本書ではまず、各種マークアップの方法を幅広く説明。
    各種のフォームやリスト、ツールバー、テーマなど、マークアップを解説します。

    さらに、jQuery Mobileを使いこなすためのテクニックを解説。
    デフォルトデザインのカスタマイズ、JavaScriptによる設定変更、
    パフォーマンスアップ、セキュリティの注意点などを紹介します。

    本書は、jQuery Mobileのさまざまな手法を網羅的に学ぶことができて、
    現場でも活用できる入門書です。
    □ □ □ □ □


    ◎短納期・低コストでリッチなサイトを制作!
    ◎モバイルサイト制作のセオリーを知らなくてもOK
    ◎多数のモバイル端末に対応


    via: Amazon.co.jp: jQuery Mobileパーフェクトガイド 基本からデザインカスタマイズ、パフォーマンスアップまで: 吉川 徹, 株式会社シーエー・モバイル: 本

    前に書いた書評 - jQuery Mobileポケットリファレンス at HouseTect, JavaScriptな情報をあなたに半年以上経ちましたが、だいぶjqmの本が充実してきていると思います。

    基本的には、jQuery Mobile: Demos and Documentationとソースコードを眺めると、何ができて何ができないのかは理解できますが、やはり書籍としてあると安心感があります。
    何よりこちらの本はフルカラー!(これは見やすい!)

    そして著者のToru Yoshikawaさんは、jqmが出たころからjqmに関するtweetや調査を行なっている方なので、出すべくして出されたという感じでしょうか。

    では、目次を。

    目次

    Chapter 1
    jQuery Mobileをはじめよう
    Chapter 2
    さまざまなフォームの使い方を知ろう
    Chapter 3
    リストを使いこなそう
    Chapter 4
    レイアウトとツールバー
    Chapter 5
    テーマを使いこなそう
    Chapter 6
    デザインをカスタマイズしよう
    Chapter 7
    jQuery Mobileの設定を変更しよう
    Chapter 8
    jQuery MobileのイベントとAPI
    Chapter 9
    パフォーマンス+セキュリティ+etc.
    Chapter 10
    [演習]モバイルサイトを作ってみよう


    とくにうれしいのが、現時点では1.2.0 Alphaが最新ですが、安定バージョンの1.1.1について書かれていることですね。
    ただし、1.1.1のlocation.hrefのバグは以下の修正版をお使いください。
    jQuery Mobileのlocation.hrefのバグに起因するXSSへの対応をjQuery Mobile 1.1.1に適用したビルドを作りました - へっぽこプログラマーの日記

    ありがたい点 - その1

    要素の装飾をしないdata-enhanceについての解説がある。
    これは、

    とセットで使いますが、意外と新し目?で入った機能なので、本で読むのは初めてでした。

    ありがたい点 - その2

    data-dom-cacheへの解説がある。
    実はこの属性はこの本で学びました。
    その昔、

    今のように1つの画面をAjaxでロードし、遷移元画面に戻ってきたときにロードしたHTMLがDomから消える
    という仕様がなく、ガンガンにページをDomに追加されていた時代

    のときのように、遷移元ページにHTMLを残したままにできます。

    ただし、一度ロードしたらそのDomを使いまわすので、頻繁に更新が掛かる画面には向かないですが、
    これはかなり使える属性だと思います。

    サンプルを書いてみました。

    ■github
    hisasann/jqmDomCache

    ありがたい点 - その3

    Chapter7 〜 Chapter9はめちゃくちゃ重要

    つまり、jqmの設定や、イベント、再装飾の仕方などなど、このあたりはやっぱり何度読んでもためになります。
    あと、vclickなどの解説もありがたい。

    ありがたい点 - その4

    ページ遷移アニメーションについての解説がしっかりしている。
    とくにAndroidの1.6〜2.3まではどのアニメーションを指定しても、強制的に「フェード」になるのは知らなかったです。

    これいつのバージョンからなんだろう。
    たしかtransform3DでCSSアニメーションが描き直されたタイミングがあったので、そのときかな。

    まとめ

    jQueryMobileの歴史はXSSとの戦いの歴史でもありますが、やはりこれほど大きいライブラリになると、
    情報の監視がとても大切になります。

    以前、jQueryMobileのXSSに関する調査メモで書いたXSSに悩まされたときもありました。

    なるべく新しい情報を取得して、それをうまくプロジェクトに反映していくのはとても大切なので、総合的に書かれている書籍が一冊あると助かります。

    ■関連記事
    jQueryMobileのかゆいところに手が届くお作法メモ
    jQueryMobileを使ってのスマートフォンサイトの構築メモ

    AppCodeのキーバインドをVimにする方法

    ここ最近AppCodeでiPhoneアプリを作っているんですが、どうやらVimのキーバインドが使えるというのを今更知ったのでメモ。
    とくにわかりにくいのが、デフォルトではVimのキーバインドはインストールされていません。
    (Emacsは入っているのに!)

    なので、Vimのプラグインをインストールしてそれを設定するだけです。

    NOTE for Vim addicts
    If you want the powers of both worlds, Vim editing capabilities and AppCode's code knowledge and others -- install the ideaVim plugin and enjoy!


    via: AppCode Basics - Objective-C IDE - Confluence

    Vimプラグインをインストールする

    AppCodeのPreferencesからPluginを選択します。

    Settings.jpg

    プラグインペインの下のほうにある「Browse repositories...」をクリック。
    開いた画面でvimを検索します。

    Browse Repositories.png

    絞りこまれたら、「ideaVIM」をダブルクリックします。

    AppCode.png

    インストールが完了すると、AppCodeの再起動を要求されるので、再起動します。
    baseとなるキーバインド(ここではdefaltを選択しました)を選んでVimのキーバインドを作成します。

    Vimのキーマップを適用する

    AppCodeのPreferencesからKeymapを選択します。

    Settings-1.png

    ここでKeymapsからVimを選べばOK、というか再起動後は自動的にVimになっているのかな?

    まとめ

    個人的に結構痛いのが「di"」や「vi"」などのダブルコートの中を削除する系が使えないこと。
    あとは自分の.vimrcで設定したキーバインドが有効にはならないので、それをどの程度AppCodeのキーバインドに登録するかですね。

    それでもほとんどVimなので、使い慣れた(僕はまだ初心者ですが)キーバインドでコードを書けるのはうれしいのではないでしょうか。

    ■関連記事
    Vimをちゃんと使い始めてみる
    AppCodeで行末尾のキャレット配置を無効にする方法

    詳解 Objective-C 2.0 第3版
    荻原 剛志
    ソフトバンククリエイティブ
    売り上げランキング: 2408

    AppCodeで行末尾のキャレット配置を無効にする方法


    ここ最近、JetBrainsのAppCodeを使って、Objective-Cを書いているんですが、デフォルトの設定だと、マウスでクリックしたところにカーソルが移動してしまう現象になっていてすごく困ったので、この機能を無効にするメモ。

    たとえば以下のようなコードがあった場合に、

    NSLog(@"%@", nsarray);

    のコードの最後のセミコロンの後ろにはスペースがいないにもかかわらず、どこでもクリックでカーソルを持っていけちゃうところ。
    セミコロンの後ろをクリックしたなら、セミコロンの後ろにマウスカーソルが移動して欲しい!

    この機能を無効にする方法

    AppCodeの「Preferences→Editor」を選択し、右側のペインで、

    Allow placement of caret after end of line

    これのチェックを外す。

    Settings.png

    これで、比較的普通なカーソル操作が可能になる。
    また、マウスだけでなくキーボードでも同様の現象になるので、これデフォルトチェックじゃないほうがいいんじゃないかなーと思いました。

    JetBrains AppCode: an Objective-C IDE That Makes a Difference

    よくわかるiPhoneアプリ開発の教科書【iOS 5&Xcode 4.2対応版】
    森巧尚
    マイナビ
    売り上げランキング: 720

    XCode4.3.2にしたときにハマったことメモ - LLDBからGDBへ

    かなりハマった。
    もうTitaniumMobile触っているときバリにハマった。

    そもそもXCode4.2で開発をしていたんですが、やっぱり4.3にしないとね!ってことで4.3にあげてTitaniumMobileも動作するように設定したんですが、肝心のXCode上でのデバッグをしようとするとXCodeが固まる現象に悩まされた。
    Titanium Mobile2.0.xでXCode4.3を使う方法

    スペック

    MacOS X
    10.7.4
    XCode
    4.3.2
    iOS SDK
    5.1

    現象

    XCodeで新規プロジェクトを作成し、とくになんのコードも書かないでRunボタンを押すと、iPhoneシミュレーターが立ち上がるがちょっとすると応答なしになる。
    よって、「Option+Cmd+Esc」から強制終了する。

    ひたすらこの現象の原因を突き止めるべく、強制終了の嵐。
    よく分からなくしていたのが、過去の4.2時代に作ったプロジェクトは普通にRunを押すとiPhoneシミュレーターが起動してくれること。

    そこでとりあえず応答なしにはなるけど、しばらくほったらかしにしてみた。
    すると、応答なし状態から抜け出し、「Attaching xxxx.app」のようなメッセージが出てきた。
    ただし、これいじょういくらまってもうんともすんとも言わない。

    やったこと

    古いXCodeのアンインストール

    やれることはやっていくしかないので、古いXCode4.2をアンインストール

    $ sudo /Developer/Library/uninstall-devtools --mode=all

    これにより「/Developer」ディレクトリの中はすんごくキレイに!

    ちなみに、FileMerge.appのような便利ツールは

    /Applications/Xcode.app/Contents/Applications

    に入っている。
    4.2時代までは/Developerに格納されていたが、4.3からはXcode.appの中に取り込まれた。

    [via]
    iOS Simulatorの導入とiPhoneシミュレータ

    XCode4.3.1にしてみたり、4.3.2を入れなおしてみたり

    これは何の効力もなかった。
    むしろ以下のように4.3.1ではバグがあるので、やっぱり4.3.2を使いたい。
    (それでもまだバグがあるようだが...)

    うたブログ~情報編: Xcode4.3.1のバグ
    うたブログ~情報編: Xcode4.3.2のバグ修正のチェック結果

    途方に暮れる

    ・・・

    いろいろやった

    以下に書かれていること全部やった。

    • プロジェクトを Clean する

    • Xcode を終了させる

    • シミュレータからアプリを削除する



    など。実機で動かしていた場合は iPhone の電源を切るというのも手だそうです。

    解決しませんでした。。



    で、最終的に行ったのが「Mac を再起動する」


    via: iPhone シミュレータ実行後、main.m で落ちる | NEO-SHOCKER.COM

    さらにMacのアップデートもやっといた。
    その昔、TiでハマったときにiTunesをアップデートすると直る現象があったため。

    どうやらLLDBというデバッガーが有効になっていたためのようだ

    XCodeがiPhoneシミュレーターにアタッチができていないことを思い出してググっていたら、以下がヒット。
    EZ-NET: iOS シミュレーターが Attaching のまま進まない - Xcode4

    でも、ちゃんとAutomaticallyになっていたので解決策ではなかった。

    そして
    デバッガの変更 - hachinobuのメモ
    こちらを読んでいて、

    xcode4.3はデバッガが今までのGDBじゃなくLLDBがデフォルトで選択されている。


    via: デバッガの変更 - hachinobuのメモ

    これやっ!
    ということでSchemeを見に行ってみたら、

    やっぱり

    LLDB

    になってた!
    そして4.2時代に作ったプロジェクトは、GDBになってた!

    なので、これをGDBにしたらすぐにiPhoneシミュレーターが起動。やっとですよ。

    まとめ

    この2種類のデバッガの違いは、まるで分からないのですが、
    LLDBを使っている人が文字化けに悩んでいたりするようなので、とりあえずGDBで行くことにします。

    というか、こっちじゃないとiPhoneシミュレーターが起動しないので。

    追伸:
    みなさん、どうしてるんだろう...

    追記:2012-05-23

    LLDBでもiPhoneシミュレーターがちゃんと起動するときがある!
    がちょ〜〜〜ん!

    よくわかるiPhoneアプリ開発の教科書【iOS 5&Xcode 4.2対応版】
    森巧尚
    マイナビ
    売り上げランキング: 1089

    Titanium Mobile2.0.xでXCode4.3を使う方法

    4.2のときにTitaniumMobileをインストールし、いろいろ遊んでいたんですが、
    XCodeが4.3になってディレクトリ構造が変わったり、コマンドライン系のツールは別でダウンロードするようになったりといろいろと違いが出てきたのでここにメモ。

    スペック

    事前にLionちゃんを10.7.4にしておきます。
    (もしかしたら10.7.3の方は上げなくても大丈夫かも)

    MacOS X
    10.7.4
    Titanium SDK
    2.0.1.GA2
    Titanium Studio
    2.0.1

    手順

    1. Downloadsより「Xcode 4.3.2 for Lionをダウンロードします。
    2. XCode4.3.2をインストールします。といっても4.3からは.appファイル単品しかないので、アプリケーションフォルダに入れましょう。
    3. XCodeを開いて「Xcode -> Preferences -> Downloads」よりcommand line toolsをインストールします。
    4. ターミナルから
      sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
      を実行します。 これによりTitaniumMobileが見に行くiOS SDKの場所を切り替えることができます。
    5. https://github.com/downloads/pegli/ios-sim/ios-sim-xcode4.3.tar.gzをダウンロードし、解凍しときます。
    6. ios-simファイルを下記ディレクトリに配置します。 一応、ぼくはすでにあるios-simファイルをリネームとかしておきました。
      cp /path/to/ios-sim ~/Library/Application\ Support/Titanium/mobilesdk/osx/2.0.1.GA2/iphone/
    7. あとはすでに存在しているプロジェクトの場合は、cleanして、Run ConfigurationsよりiOS5.1を選んでビルドすれば完成です。 新規にプロジェクトを作った場合は、自動的にiOS5.1になります。

    ■関連リンク
    Titanium 1.8.xをXcode 4.3環境で使用するには? - Titanium News
    Titanium MobileでiOS 5.1(もしくはXcode 4.3)を扱う : Shibuya Blog
    Titanium and Xcode 4.3: Revisited « Appcelerator Developer Center

    ■関連記事
    MacOSX LionにTitanium Mobile(Studioも)をインストールしたときのメモ(2012-02-06時点)
    TitaniumMobileのハマりポイントとお作法メモ
    MacOSX LionにPhoneGapをインストールしたときのメモ(2012-02-09時点) - iPhone/Android対応

    Titanium Mobileで開発するiPhone/Androidアプリ (Smart Mobile Developer)
    北尾 雅人
    翔泳社
    売り上げランキング: 105027

    TitaniumMobileのハマりポイントとお作法メモ

    ここ最近TitaniumMobileの主に検証を行なっております。

    そして先日Titanium meetup Tokyo #17 (五反田) : ATNDにおじゃまして@masuidriveをはじめとする多くのTitaniumMobileファンの方々とお話ができました。
    すごく楽しかったです!

    僕がTitaniumMobileに触り始めて約一ヶ月ほどたちますが、ハマったポイントをつらつらメモしてみました。
    使い方やTitaniumMobile自体のバグなど、まだ難しい部分は多々ありますが、4月に2.0がリリースされるようなので、今後が本当に期待できるフレームワークです。

    スペック

    簡単に今のぼくの環境をご紹介。

    MacOS X
    Lion
    Java
    1.6.0_29
    Titanium SDK
    1.8.2
    Titanium Studio
    1.0.9


    requireをAndroidで使えるようにするため、tiapp.xmlにfastdevを無効にするタグを追加

    CommonJSでコーディングする際、requireで外部のJavaScriptファイルを読み込むことが非常に多くなりますが、
    このパスがfastdevを有効にしているとうまくいかない。
    Titanium mobile -- Android でrequire()エラー - WEBサービス 情報局

    Androidの場合だけですが、

    が「Resources/lib/lib/a.js」のようになってしまう。
    これは、Titanium1.6までのTi.includeと同じ現象かなーと思っています。
    libの階層が一個多い!!
    Titaniumのインクルードパスを指定する方法私案 - もぎゃろぐ

    なので、以下のように非常に残念ですが、fastdevを無効にするタグをtiapp.xmlに入れましょう!

    1.8現在、まだこのバグが直っていないので、今後に期待ですね。
    とはいえ、Androidのデバッグは以下で紹介しますが、DDMSというツールを使って実機で行なっているので、
    fastdevの恩恵はそもそも受けられなかったです。


    アプリのバージョンを取得する方法

    tiapp.xmlの

    に書いたのアプリバージョンになります。
    そして以下が取得コード

    アプリを段階的にリリースする際などに、このバージョンを見て処理を分けたりできますね。

    [via]
    Office L テクニカルノート


    JSSはプロジェクトをcleanしないと修正したものが反映されない問題!とかあといろいろ

    以下が簡単なJSSサンプル。

    app.js

    app.jss

    こちらのJSSファイルに記述したCSSっぽいものが、この場合はidに紐づいて反映されるが、
    プロジェクトのcleanをしないと反映がされない。
    つまり以下のredをblackにしてRunしなおしても反映されないのだ。

    TitaniumのJSSという機能 | ひげろぐの記事を読むと1.6で修正されたとあるので、もしかしたら1.8で再度このバグが出たのかな?

    また、以下の記事を読むとやっぱりまだJSSを使うときじゃないのかなーと思っています。1.6の記事ではありますが。
    Titanium Mobile でCSS的な、それJSS!!!!!! | MOL

    なので、Zaimで採用されているTitanium でつくろう! iPhone/Android 両対応アプリのような方法よいかもしれません。
    (この方法すばらしいと思います!)


    iPhoneの場合CommonJSのrequireで呼び出されたモジュール内でグローバル変数が見れる

    以下のようなシンプルなサンプルでiPhone、Androidで試してみましたが、
    iPhoneの場合にhogeがtestmodule内から見えてしまいました。

    一応node.jsで同じことをやってみましたが、hogeが見えなかったです。

    app.js

    testmodule.js

    以下の和訳ページを見てみると、

    TiにおけるCommonJSモジュールの仕様の実装はnode.jsのものに基づいています。


    via: CommonJS Modules in Titanium - JP::HSJ::Junknews::HatenaSide

    アプリケーション内のすべてのモジュールにわたって共有されるグローバル変数は存在してはいけません。


    via: CommonJS Modules in Titanium - JP::HSJ::Junknews::HatenaSide

    と書いてあることから、このパターンだとiPhoneの場合のrequireがヘンテコなことになっているのかな?
    なので、無名関数で囲ってあげる。

    Androidのエラー内容

    DDMS(↓のほうで解説)で調べた内容。

    02-27 14:46:27.499: E/TiJSError(2137): (main) [311,706] ----- Titanium Javascript Runtime Error -----
    02-27 14:46:27.499: E/TiJSError(2137): (main) [1,707] - In testmodule.js:5,36
    02-27 14:46:27.499: E/TiJSError(2137): (main) [0,707] - Message: Uncaught ReferenceError: hoge is not defined
    02-27 14:46:27.499: E/TiJSError(2137): (main) [0,707] - Source: Ti.API.log('aaaaaaaaaaaaaaaa: ' + hoge);
    02-27 14:46:27.539: E/V8Exception(2137): Exception occurred at testmodule.js:5: Uncaught ReferenceError: hoge is not defined

    iPhoneのエラー内容

    無名関数でapp.js内を囲うと以下のエラーが出た。

    [ERROR] Script Error = Can't find variable: hoge (unknown file).

    ■参考リンク
    CommonJS Modules in Titanium - Documentation & Guides - Appcelerator Wiki
    俺流コーディングスタイルにダメ出し - toweroflの日記
    Titanium Mobile Best Practices - JP::HSJ::Junknews::HatenaSide


    TextMate風なスニペットで楽々開発!

    20111205233655.png

    [via]
    【Titanium Advent Calendar 2011:八日目】タイタにうもん第1話 - JP::HSJ::Junknews::HatenaSide

    このスニペットのおかげで、buttonと入れてtabを押せばビヨッと展開されるし、webviewって入れてもいいし、infoって入れてもいいしね。
    このコード補完は非常に強力です!(どうしてcreateWindowはないんだろう。)


    .svnディレクトリが悪さするから、gitを使おう?

    以下の記事によると、

    私みたいに、会社の都合等で、gitが使えずにSVN使っている方いますよね。
    なんと、TitaniumStudioにて、SVNチェックアウトしたAndroid用プロジェクトを、RunやDistributeしようとすると、失敗しちゃいます><。
    画像の生成のところで失敗しているみたいですね><。


    via: 【Titanium Advent Calendar 2011:十日目】

    となっていて、svn exportしてからbuilder.pyを呼び出すということをされています。
    ちょっと僕のほうで確認ができていないのですが、確かにすべてのディレクトリに.svnがいるのはちょっといやだなーと思うので、思い切ってgitを採用しちゃうのもありですね。

    こちらSession01 - Android バットノウハウつめあわせ on Vimeoでも同じようにgitを使おうって話しになっていて面白かったです。


    アプリ名の変更はプロジェクトの作り直しが楽?

    Androidだと、

    02-27 19:48:11.943: E/AndroidRuntime(6196): java.lang.RuntimeException: Unable to instantiate application com.hisasann.Hoge.HogeApplication: java.lang.ClassNotFoundException: com.hisasann.Hoge.HogeApplication in loader dalvik.system.PathClassLoader[/data/app/com.hisasann.Hoge-1.apk]
    02-27 19:48:11.943: E/AndroidRuntime(6196): at android.app.LoadedApk.makeApplication(LoadedApk.java:466)
    02-27 19:48:11.943: E/AndroidRuntime(6196): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3287)
    02-27 19:48:11.943: E/AndroidRuntime(6196): at android.app.ActivityThread.access$2200(ActivityThread.java:121)

    が出る。

    【Titanium Advent Calendar 2011:一日目】既にリリースしたアプリ名の変更(AppStore編) | MOL
    にあるリンク先に、

    Because of generated files and complexity with renaming some of them, we decided against allowing editing. You can create a new project and just copy in your Resources to the new project (and then just delete old).


    via: How can i rename my iphone app project? » Community Questions & Answers » Appcelerator Developer Center

    と書いてあるので、たしかにへんなエラーで(ClassNotFoundException)で悩むぐらいなら、新しくプロジェクト作ってリソースコピーしちゃえ!


    ファイル名にアンダースコアが付いているとAndroidの実機にインストールできない

    Titaniumでアンダースコア付きのファイルはやめておいたほうがよいみたい。

    [ERROR] /TitaniumStudioWorkspace/Sample-LocalJqm/Resources/jqm/js/jquery.mobile-1.0.1/demos/docs/_assets/js/_viewsource.js is an invalid filename. Android will not package assets whose filenames start with underscores. Fix and rebuild.

    このようにjquery.mobile-1.0.1の下にあるdemoディレクトリ内にアンダースコア付きのファイルがあって、iPhoneだと実機にインストールできますが、Androidでは入らない。

    [via]
    pd @ blogger: Titanium Mobile 1.8 からの変更点?ビルドが進まない。
    (こちらの記事のV8が速いという記事、ちょっとグッときました)


    ローカルHTMLの場合historyが記録されないのでjQueryMobileの戻るボタンは反応しない

    httpで読み込むなどした、外部のサイトならOK!
    ローカルHTMLの場合は、戻るボタンを押してもうんともすんともいってくれない。

    [via]
    Titanium の WebView で HTML をホスト | アカベコマイリ


    Ti.Media.showCamera(カメラ)を使ってみる

    古いバージョンではAndroidの場合に、tiapp.xmlに以下のようにパーミッションを追記する必要があるかもしれません。
    現時点で検証している1.8.1と1.8.2では、デフォルトでAndroidのカメラパーミションがもれなく付いてきています。

    iPhoneは特になんの設定もしなくても使えます。

    ■カメラを使ったサンプルコード
    TitaniumMobileでカメラを使う方法 -- Gist

    ちなみにここで、カメラのパーミションを追記していますが、僕個人としては、のちのちのことを考えると次でご紹介するAndroidManifest.xmlに追記する方法をおすすめします。


    Xperia arcでカメラを使うと予期せぬ強制終了が発生する

    Androidのバージョンは2.3.2だが、何をどうしてもカメラを撮影したタイミングで落ちてしまう。
    具体的なコードは以下のとおり。
    至って普通のカメラ呼び出しだが、この引数に渡しているオブジェクトのプロパティをいろいろいじってみたが100%落ちる
    Xperia arcは比較的シェアが高めな端末なので、こうなるとカメラの機能は自前でモジュールとして作成するか、必要がないなら使わないなどの対策が必要が気がしています。

    [#TIMOB-4899] Camera crashes Sony Ericsson Xperia Arc Android 2.3.2, 2.3.3 with all branches - Appcelerator JIRA

    Androidが落ちた時のエラー

    02-21 09:59:02.214: E/TiApplication(17570): (main) [681,31285] Sending event: exception on thread: main msg:java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data dat=file:///sdcard/dcim/Camera/tia-1288732183.jpg typ=image/jpeg (has extras) }} to activity {com.hisasann.Baruth/org.appcelerator.titanium.TiActivity}: java.lang.NullPointerException; Titanium 1.8.1,2012/01/27 17:31,a24502a
    02-21 09:59:02.214: E/TiApplication(17570): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data dat=file:///sdcard/dcim/Camera/tia-1288732183.jpg typ=image/jpeg (has extras) }} to activity {com.hisasann.Baruth/org.appcelerator.titanium.TiActivity}: java.lang.NullPointerException
    02-21 09:59:02.214: E/TiApplication(17570): at android.app.ActivityThread.deliverResults(ActivityThread.java:2504)

    どうもintentまわりでヌルポが発生しているように見える。
    なんとなくだが、

    Sony Ericsson Xperia Arc has a branded Android version, and a special camera (also camera software).


    via: [#TIMOB-4899] Camera crashes Sony Ericsson Xperia Arc Android 2.3.2, 2.3.3 with all branches - Appcelerator JIRA

    と書いてあるとおり、もしかしたらarcはカメラのアプリが特殊なので、intentに失敗しているのかも?


    AndroidManifest.xmlにAndroidの設定を追記してみる

    Androidの設定は、AndroidManifest.xmlファイルに書き出されます。
    細かい部分は、a. AndroidManifest.xml ファイル - ソフトウェア技術ドキュメントを勝手に翻訳を参照ください。

    んで、このファイルがTitaniumの場合どこにあるかと言いますと、

    /[プロジェクト名]/build/android/AndroidManifest.xml

    になります。

    一度でもAndroidでビルドしているとこのファイルができていますので、試しに見てみましょう!

    下のほうにいくと

    と書かれていますね。
    つまり、TitaniumMobileの場合は、デフォルトでカメラが使える状態なのです。

    この場所に置かれているAndroidManifest.xmlはビルドするたびに作りなおされてしまいますので、
    プロジェクト内に配置して、うまいことマージしてもらいましょう。

    TitaniumStudioから以下のディレクトリに↑のファイルをコピーする。

    /[プロジェクト名]/platform/android/AndroidManifest.xml

    これで、ビルド時にここのファイルを見に行ってくれるので、Android特有の設定はここに追記していく。
    tiapp.xmlに書いていく方法もあるようなのですが、実はあんまりよく理解できませんでした。
    そして、最終的にこっちに書かないとうまくいかない設定があったりなどで、このスタイルに落ち着いています。


    iPhoneとAndroidでwidthなどのサイズの指定をどうするか

    これはまだ最終的な策が出ていませんが、現時点でこうかなーという感じで書いてみます。
    そもそもの話しですが、たとえばwidth:'320px'とこれは、400pxではなく300pxでもなく320pxです。
    つまりiPhoneでは横幅いっぱいですが、他のAndroidなどは画面の中央ぐらいまでの場合もあります。

    これだと各端末の場合はというif文が存在してしまい、とてつもなく大変なことになります。
    これをうまいこと吸収してくれる?のがdp(だと思います)

    Y.A.M の 雑記帳: Android multi screen 対応
    を参考にさせていただいて、AndroidManifest.xmlに追記しました。

    そして、プログラム内でサイズを指定する箇所は「width : '320dp'」のようにdpと指定しています。
    dpに関する内容は、以下が詳しかったです。

    画面の物理的な密度に基づいた抽象的な単位。
    この単位は 160 dpi の画面と対応していて、160 dpi の画面で 1 dp = 1 px になる。なので、dp-pixel 比は画面密度(解像度)に応じて変化するが、必ずしも正比例するわけではない。


    via: Y.A.M の 雑記帳: Android Dimension 単位

    dpiが160の場合は320dpは320pxなんですが、このdpiが変わって240になると320dpが480pxになったりします。

    ちょっとだけ厄介なのが、iPhoneのエミュレータは160dpiですが、iPhone4Sの実機で試したところ320dpiが返ってきました。
    なんというRetina Displayよ!


    dp指定の場合のanimateはどうしよう

    Titaniumのアニメーションは非常に便利で、以下のように書くだけで動いてくれます。
    jQueryみたい!

    ここで問題なのが、heightやtopなどにはInt値しか渡せないことです。
    つまり、

    はエラーになります。
    これを回避するために、以下のようなコードを書きたいところですが、iPhone4Sだとdpiが320なので、320dpを渡すと640が返ってきてしまいます。

    現時点ではAndroidの場合に上記コードを実行するようにしていますが、果たしてiPadでうまいこといくのかどうか。
    今後、確認します。


    アプリを縦向き固定(portrait)のみにする

    iPhoneの場合は、tiapp.xmlに以下のように記述すればよいのですが、

    Androidは、AndroidManifest.xmlに記述します。
    これは結構ネットでもいろんな記述されている方が多く、またそれらが古いバージョンでは動くが現バージョンでは動かないなどがあり結果このスタイルに落ち着きました。

    ■最終的なAndroidManifest.xml
    AndroidManifest.xmlのサンプル、縦固定などなど。 -- Gist

    ちなみにJavaScriptからもできるようです。

    ただ、気をつけることはTitanium.UI.createWindowするときには指定せず、そのあとにorientationModesをセットしないとダメのようです。
    むむっ!


    存在しないオブジェクトプロパティの値がiPhoneとAndroidで異なる

    以下のようなコードを書いたときにiPhoneとAndroidで結果が異なる。

    iPhoneの結果

    [INFO] <null>

    Androidの結果

    03-05 09:23:05.243: I/TiAPI(5644): undefined

    とはいえ、

    という書き方すれば大丈夫ですね。

    [via]
    Session01 - Android バットノウハウつめあわせ on Vimeo


    Androidの場合HttpClientとWebViewでcookieが共有されない

    以下のようのPHPコードでCookieの共有検証をしてみました。

    クッキーにセットした値をカウントアップします。 -- Gist

    結果、

    • iPhoneは共有される。ただし、アプリをkillするとCookieは消去される。
    • Androidは共有されない

    Androidのほうの共有されない問題は、じつは結構でかい問題で、特にログイン機能を持っているアプリの場合に厳しいと思います。
    これみなさんどうしてるんですかね。

    なので、CookieよりはTi.App.Propertiesを使うほうが確かかもしれません。

    [via]
    Session01 - Android バットノウハウつめあわせ on Vimeo


    httpsなサイトをWebViewで開く場合は証明書が大事!

    httpsなURLにアクセスする際にオレオレ証明書だとアクセスすることができません。
    その挙動がiPhoneとAndroidで違うので以下にメモ。

    iPhoneで接続した場合

    ちゃんとcertificateのエラーが出てくれる。

    [ERROR] Error loading: https://hogehoge.com/, Error: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be "hogehoge.com" which could put your confidential information at risk." UserInfo=0xa812dd0 {NSErrorFailingURLStringKey=https://hogehoge.com/, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSErrorFailingURLKey=https://hogehoge.com/, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be "hogehoge.com" which could put your confidential information at risk., NSUnderlyingError=0x8c315f0 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be "hogehoge.com" which could put your confidential information at risk.", NSURLErrorFailingURLPeerTrustErrorKey=}

    Androidの場合

    何もエラーが出ず、画面にHTMLも表示されない。
    つまり一見するとハマる。


    Ti.Network.createHTTPClientで証明書がないhttpsを開けるけども?

    以下のようにTitanium.Network.HTTPClientのvalidatesSecureCertificateというプロパティをfalseにすると、証明書がないhttpsなURLでも通信することができる。

    ただし、

    validatesSecureCertificateはシミュレータや実機テスト時はfalseだけど、リリース用の時は強制的にtrueなのかな? / "Does titanium mobile supports SSL with htt..."


    via: Twitter / @hisasann: validatesSecureCertificate ...

    なんか自分でもつぶやいていますが、
    Does titanium mobile supports SSL with https URLs ? » Community Questions & Answers » Appcelerator Developer Center
    によると、デプロイするとデフォルトtrueで上書きができないんじゃないかなーって思っています。(未検証)

    アプリ開発ではこのhttpsなんだけど証明書がないケースでのテストができないこともあるので、
    ちょっとテストがしにくいですね。


    WebViewとTitaniumの連携 - ローカルHTML(アプリ内HTML)からTitaniumのイベントをfire

    app.jsの一部

    WebViewで読み込まれたローカルHTMLの一部

    ちなみにですが、リモートのHTMLをWebViewに読み込んだ場合は、上記コードは動かない。
    あたりまえですが、勝手にexternalなサイトからアプリ内のイベントを呼ばれちゃうのは困る。

    場当たり的にいろんな名前でイベントfireしまくれば、もしかしたら一個ぐらいは動くかも?

    ただし、HTML 内から Titanium オブジェクトを呼び出すのは、ローカルに保存された HTML でないといけません。


    via: MountPosition Inc. » TitaniumでWebView にイベントリスナを登録する

    ■参考リンク
    Titanium の WebView で HTML をホスト | アカベコマイリ
    addeventlistener - Trouble using Titanium's webview to fire an API event - Stack Overflow
    WebViweに表示されているHTMLからTitaniumの処理を実行する | ひげろぐ


    WebViewとTitaniumの連携 - Titaniumから読み込んだHTMLを操作する

    WebViewにロードしたHTMLをload後に書き換える方法

    これはコードで見たほうが早いですね。

    app.js

    WebView.js

    TitaniumMobileでWebViewを使う方法 -- Gist

    上記の、

    で行なっています。
    ただし、まだ僕もよく分かっていませんが、構文にミスがあっても、うんともすんともエラーを出してくれません。
    よって、デバッグがかなり大変になります。
    なので、この処理はあくまでもヘッダー・フッターをdisplay:none;にしたいなど、
    そういった比較的軽めな対応にしておいたほうがよさそうです。

    また、このevalJSは複数行のコードを評価させると、1行目しか実行してくれません。(Androidの場合だけっ!)
    つまり、以下のコードを実行すると、

    alertは出ますが、テキストボックスの値は変わりません。
    セミコロン1個までじゃないとダメなので、もし複数行のJavaScriptを実行する場合は、

    と書くようです。
    難しい!

    [via]
    【Titanium Advent Calendar 2011:二日目】evalJSの恐怖 - もぎゃろぐ


    adbコマンドでAndroidデバイスを知る!

    接続されているAndroidデバイスの確認は、

    adb devices

    ログは、

    adb logcat

    複数接続されている場合は、デバイス番号を指定する。

    adb -s [デバイス番号] logcat

    [via]
    複数デバイスが動いているときにログを見る - ore*flow


    AndroidのWebViewではlocalStorageが使えない

    いろいろ試していてハマったんですが、AndroidのWebViewでlocalStoragenullになってしまう。
    WebViewではなくブラウザではOK。

    調べていくと、ネイティブだと以下のようなコードをWebViewを呼ぶ前にする必要があるみたい。

    [via]
    Android WebView で HTML5 の Web Storage と Web SQL Database API を使う - nobnakの日記

    でも、この設定をできるコードがTitaniumに見つからない。

    以下のようにいろんな人たちがハマっていて、これは今後どうなるんだろう。
    Localstorage failure in webview » Community Questions & Answers » Appcelerator Developer Center
    Webview - Enabling localStorage » Community Questions & Answers » Appcelerator Developer Center
    how to enable localStorage iun Android » Community Questions & Answers » Appcelerator Developer Center
    Twitter / @hisasann: AndroidのWebViewでlocalStora ...

    外部サイトを読み込み、かつlocalStorageを使いたい場合は、Titanium.Platform.openURLブラウザを開いてあげるしかないのかな。
    あとはTitanium.App.Properties.setStringを使ってなんとか、アプリ側に値を保持して、うまいことやる?
    ちょっとややこしいですな。


    Titanium-Google-Analyticsでトラッキング

    rogchap/Titanium-Google-Analyticsを使ってできるようです。(未検証)

    こちらの記事が参考になります。
    Titanium MobileでGoogle Analyticsを利用する - box box box


    Ti.Appにグローバルな変数を入れて共有する

    引数で渡すよりもグローバル化したほうが効率的なシチュエーションがあるので、Ti.Appにいろいろぶらさげて管理したいところ。
    ただ、Ti.App配下にはすでにたくさんのプロパティやらメソッドがあるので、これらを壊さず、かつ、開発者が追加したというのが分かるようにしたい。

    ということで、

    みたいに、一つワンクッションを入れて、プロパティを管理しようと思いました。
    ところが、

    としても、hogeがnullのままになるという減少に悩まされました。
    なので、以下のコードで検証。

    なんだこれ。。。
    なので、function(){}を使って名前空間を作っています。

    ちなみにですが、名前空間を使わず、以下のように入れれるので、面倒な方は以下の方法ですかね。

    [via]
    Ti.Appにオブジェクトをくっつけてグローバル変数的に使う | ひげろぐ


    僕のiPhone、Androidのデバッグ環境

    本来ならiPhoneもAndroidもエミュレータを起動して確認して、その後に実機に入れて確認という感じになるとは思うのですが、
    僕の環境ではAndroidエミュレータを起動した際(ランダム)にMacが強制的に落とさないといけない状況になります。
    具体的にどうなるかはInstagramこちらをご覧ください。
    (どうやらカーネルパニックのようです)
    Androidエミュレータを起動したときのMacのエラーログ -- Gist

    それに、↑のほうで解説したようにfastdevを使った状態だとrequire時のパスがヘンテコになります。
    もう、これだけ揃うとエミュレータで作業する意味があまりないので、実機でのデバッグになります。

    ちなみにですが、エミュレータの起動は死ぬほど重いですが、実機への転送は意外と速いです。

    Androidのデバッグについて

    会社の方に教えていただいたのが、このDDMSという付属ツール。
    以下の場所にあります。(Androidを触り始めて1週間でこのツールの存在を知りました!遅い!)

    android-sdk-macosx/tools/ddms

    僕は、しょっちゅう使うので、aliasにして.bash_profileに書いちゃいました。

    alias ddms="~/_/dev/android-sdk-macosx/tools/ddms"

    ■参考リンク
    AndroidのDDMSの使用方法のドキュメントを翻訳しました - Android(アンドロイド)情報-ブリリアントサービス

    Androidの実機をMacに接続し、あとはRunのボタンのAndroid Deviceを選んでちょいとまちます。
    すると、

    [INFO] Application installed. Launch from drawer on Home Screen

    と出るので、Androidのアプリのところから自分のアプリを起動します。
    ここで、ちょっとしたことではなりますが、僕はTi.API.logではなくTi.API.errorを使ってログを吐くようにしています。
    logほうでもいいんですが、流れるスピードが尋常じゃないので、errorで出力しておいて、
    DDMS側のログレベルをerrorにしています。

    それかSaved FiltersのところでFilterを作っちゃうかですね。

    もっといい方法があるだろう。

    iPhoneのデバッグについて

    iPhone側はなんの問題もありません。
    エミュレータでガシガシ開発しています!
    しかもエミュレータ起動速い!いいね!


    Jasmineを使ってテストをする

    すでにあるguilhermechapiewski/titanium-jasmineこちらをCommonJS対応し、ディレクトリ構成を綺麗にした版

    hisasann/titanium-jasmine

    を作ってみました。

    普通に起動したいなら、

    make run-iphone

    テストとして起動したいなら、

    make test-iphone

    クリーンしてから起動したいなら、

    make clean && make run-ipad

    TitaniumStudioから普通に起動しても問題ありません。


    TitaniumMobileで作られたアプリ

    1. Zaim
    2. はてなカウンティング
    3. 積ん読本
    4. Wunderlist
    5. Nyars
    6. そうしてあなたはさっていくのね
    7. POPCORN S
    8. NIFTY-Serve
    9. Sptted
    10. MogSmash(MogSnapって今動かないですよね?)

    こちらにかなりまとまっています。
    Titanium Mobileの開発事例 « Titanium BBS(JP unofficial)


    是非読んでいただきたい記事やスライドや動画やコード!

    小さな Titanium Mobile の読み物

    JavaScriptを使って一週間でiPhoneアプリを作ってみた。 - おんがえしの日記

    Session06 - TitaniumでiOS/Android同時リリース:NIFTY-Serveの事例 from astronaughts on Vimeo.

    Session07 - MogSnap 開発秘話&すぐに使える Titanium アニメーションテク from astronaughts on Vimeo.

    toru0325/TKAnimationSample

    toru0325/TiMetro - GitHub


    まとめ

    とにかくハマる!
    ハマる!
    ハマる!

    でも、ふと思ったんですが、そりゃiPhoneとAndroidの両方をJavaScriptで開発し、かつ同じコードでもそこそこ動く環境という時点で非常にありがたい。
    あとはUIを分けるなどして、分岐していくのかなーと思いますが、iPhoneではアニメーションすごくいい!Androidだとそこそこいい!なので、これから流行ってきそうですね。

    Titanium Mobile 2.0リリース発表を東京でも行います! 詳細は後日公開しますが4/20の予定となっています!参加しようかな?と思う方はFavを頂けるとうれしいです!


    via: Twitter / @masuidrive: Titanium Mobile 2.0リリース発表を ...

    TitaniumMobile2.0期待!

    Titanium Mobileで開発するiPhone/Androidアプリ (Smart Mobile Developer)
    北尾 雅人
    翔泳社
    売り上げランキング: 11403

    TortoiseGitとmsysgitではじめるWindowsGit生活

    Windowsにgitを入れたことがなかったので、比較的ラクに導入する方法をいろいろ調べてみたところ、TortoiseSVNならぬTortoiseGITがあったので、これの導入までをメモ。

    このTortoiseGITを使えば、コードとか書かないけどWindows上でgit使わないといけなくなってしまったPMさんとかデザイナーさんでも安心してgitを使うことができると思います。

    TortoiseGitを使うには、msysgitというツールをインストールする必要があります。
    このmsysgitがgitの実体です。
    その昔、Cygwinを入れて、gitを使うという方法があったようですが、今はこのツールだけあればgitが使えます。(日本語が使えないですが)

    msysgitのインストール

    InstallMSysGit · msysgit/msysgit Wiki

    以下から、msysGit-fullinstall-1.7.9-preview20120201.exeをダウンロードします。
    Downloads - msysgit - Git for Windows - Google Project Hosting

    展開先を「C:\msysgit」のままにして実行しました。
    もし他のパスがよい場合は適宜変更してください。

    Windows 7 x64.png

    すると、上の画像のようなコンソールが出てきます。
    これでインストールは完了だとは思うのですが、

    InstallMSysGit · msysgit/msysgit Wikiに書いてある以下のシェルを実行しときました。

    /share/msysGit/initialize.sh

    このmsysgitの面白いところが、Unixコマンドが打てることです。
    llとかpwdとかUnix上で使っていたコマンドが使えます。

    サイドこのプロンプトを開きたいときは、

    C:\msysgit\msysgit\msys.bat

    を実行します。
    なので、このファイルのショートカットを作っておくと便利かもしれません。

    あと、msysgitはssh-keygenが使えます!

    gitの設定ファイル「.gitconfig」の場所

    C:\Users\hoge\.gitconfig

    ここにおいてあります。

    せっかくなので、コンソールからグローバルなユーザー名とメールアドレスを設定しちゃいましょう。
    msys.batを起動して、以下のコマンドを打ちます。
    ユーザー名とメールアドレスは適宜読み替えてください。

    git config --global user.name "hoge"
    git config --global user.email "hoge@hoge.com"

    では環境設定を表示してみましょう。

    git var -l

    user.nameuser.emailがちゃんと反映されています。

    core.symlinks=false
    core.autocrlf=true
    color.diff=auto
    color.status=auto
    color.branch=auto
    color.interactive=true
    pack.packsizelimit=2g
    help.format=html
    http.sslcainfo=/mingw/bin/curl-ca-bundle.crt
    sendemail.smtpserver=/mingw/bin/msmtp.exe
    diff.astextplain.textconv=astextplain
    rebase.autosquash=true
    http.proxy=
    user.name=hoge
    user.email=hoge@hoge.com
    core.repositoryformatversion=0
    core.filemode=false
    core.bare=false
    core.logallrefupdates=true
    core.symlinks=false
    core.ignorecase=true
    core.hidedotfiles=dotGitOnly
    remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
    remote.origin.url=c:/_/dev/gittestrepos/test.git/
    branch.master.remote=origin
    branch.master.merge=refs/heads/master
    GIT_COMMITTER_IDENT=hoge hoge@hoge.com 1331271139 +0900
    GIT_AUTHOR_IDENT=hoge hoge@hoge.com 1331271139 +0900
    GIT_EDITOR=vi
    GIT_PAGER=less

    TortoiseGITのインストール

    tortoisegit - Porting TortoiseSVN to TortoiseGIT - Google Project Hosting

    以下から、TortoiseGit-1.7.7.0-64bit.msiをダウンロードします。
    32bitな方は、32bitのほうをダウンロードしてください。
    Downloads - tortoisegit - Porting TortoiseSVN to TortoiseGIT - Google Project Hosting

    TortoiseGitのインストール時には使用するSSHクライアントを設定するが、GUIメインで利用するなら「TortoisePLink」を利用する設定にすると使い勝手が良いだろう


    via: 実用レベルに達したWindows向けGitクライアント「TortoiseGit」でGitを始めよう - SourceForge.JP Magazine : オープンソースの話題満載

    これを呼んだので、特に何も迷わずに次へ次へと進んでみました。
    これでインストールは完了。
    すごく簡単!

    ちなみに、msysgitのコンソールから「git commit -m 'テスト'」のように日本語を入力することができません。
    ですが、TortoiseGITからのcommitでは日本語が通るので問題ありませんね。

    あとは、使って慣れる!
    git - 簡単ガイドとか読んで慣れる!

    番外編 - リモートリポジトリをローカルに配置してちょっとしたバージョン用にgitを使ってみる

    僕はブログの記事(比較的長文)を書くときは、間違えてファイルを消したりしたとき用にgitを使ってバージョン管理しています。
    一般的にはローカルのリポジトリで作業して、リモート(別のサーバーや端末)に対してpushすると思うのですが、そこまでしないけどバージョンしたいときに以下のようにして使っています。

    ローカルでリポジトリを作成する

    % cd 適当なディレクトリ
    % mkdir gittest
    % cd gittest
    % git init

    % touch README
    % git add README
    % git commit -m 'first commit'

    ローカルでリモートリポジトリを作成する

    % mkdir /c/gittestrepos/gittest.git
    % cd /c/gittestrepos/gittest.git
    % git --bare init

    ローカルからローカルにあるリモートリポジトリにpushする

    % cd 適当なディレクトリ
    % git remote add localrepos /c/gittestrepos/gittest.git
    % git push localrepos master

    上記ではmsysgitを使ってやってみました。
    /c/というのがCドライブになります。

    このように別にリモートだからといって、別の端末になくてもいいんですよね。
    このあとに、もしgithubにコミットしたいと思ったときはremoteをaddすればよいので、楽チンかなーと思います。

    ■参考リンク
    Git/一人で使ってみる(msysgit編) - 俺の基地
    Git/インストール(WindowsXP編) - 俺の基地
    msysgitインストール 〜 sshでのgitリポジトリアクセスまで | Happy my life
    せっかちな人のための git 入門 - git をインストールし、共同で開発できる環境を整えるまで - 僕は発展途上技術者

    Gitによるバージョン管理
    岩松 信洋 上川 純一 まえだこうへい 小川 伸一郎
    オーム社
    売り上げランキング: 24163

    githubのgh-pagesブランチを使って自作サイトを表示する方法

    こちらの30分、JavaScriptで作るWebサービスのモックアップ - ゆーすけべー日記記事を拝見して、僕もざっくりとしたInstagramAPIを使ったサイトを作ってみた。

    ひたすらラーメンの写真を表示するInstagramサイト - Ramenstagram

    Ramenstagram

    ひたすらBlackMilの写真を表示するInstagramサイト - I Love BlackMilk!

    I Love BlackMilk!

    またくだらないものを・・・

    githubリポジトリを作る

    ではではまずはgithubのリポジトリを作りましょう!

    githubでリポジトリを作り、ローカルで以下のように実行する。
    基本的なgithubの手順ですね。

    mkdir Ramenstagram
    cd Ramenstagram/
    git init
    touch README
    git add README
    git commit -m 'first commit'
    git remote add origin git@github.com:hisasann/Ramenstagram.git
    git push -u origin master

    gh-pagesブランチを作成する

    GitHub Pages - Homeに書いてあるとおりですが、以下のようにコマンドを実行してブランチを作成します。

    cd Ramenstagram/
    git symbolic-ref HEAD refs/heads/gh-pages
    rm .git/index
    git clean -fdx
    echo "My GitHub Page" > index.html
    git add .
    git commit -a -m "First pages commit"
    git push origin gh-pages

    これでgit branchしてみると、

    * gh-pages
    master

    となっているので、現在作業中のブランチは「gh-pages」ということになる。

    githubサイトにて

    adminボタンをクリック。

    すると以下の画像のように、すでにGitHub Pagesが作られていて、チェックボックスにチェックが入っている。
    これは、gh-pagesというブランチを作ると自動的にチェックが入るよう。
    逆にgitコマンドからではなく、adminページにて、チェックを入れても同じようにgh-pagesブランチが作られる。
    どっちが楽かはあなた次第!

    Administration for hisasann_Ramenstagram - GitHub.png

    そして、
    http://hisasann.github.com/Ramenstagram
    にアクセスしてみると、ちょっと待っててよ的な画面が。

    GitHub Pages - File Not Found - GitHub-2.png

    少し時間を置くと以下のようにindex.htmlの内容が表示された!

    GitHub Pages - File Not Found - GitHub-1.png

    あとは、このブランチに自分のサイト用のHTMLやらJavaScriptやらCSSやらを配置してコミットすれば自動的に反映される!
    便利!

    InstagramのtagAPIを使ってJSONを返すnode.jsコード

    ちなみにInstagramのJSONを取得しているのはnode.jsで作っています。

    フロントのJavaScriptだけで完結したほうが綺麗なんですが、access_tokenをバレたくないので、いったんこのnodeがプロキシになってInstagramのtag情報から画像を返すようにしています。

    InstagramのtagAPIを使ってJSONを返すnode.js版プロキシー -- Gist

    ■参考リンク
    実践GitHub Pages運用のユースケースとワークフローの詳細 | ゆっくりと...
    GithubのProject Pagesを作る手順を調べてみた。もしくはgitで空ブランチを作る方法を調べてみた。 - kanonjiの日記

    入門git
    入門git
    posted with amazlet at 12.02.24
    Travis Swicegood
    オーム社
    売り上げランキング: 10517

    クロスドメイン用のHTTPレスポンスヘッダー - Perlスクリプト版

    iPhoneのSafariとAndroidのブラウザ、PCのSafariとChromeでクロスドメインなAjaxを行う場合のレスポンスヘッダーで地味にハマったので、忘れないうちにメモしとく。

    たいていの場合、.htaccessファイルに「Access-Control-Allow-Origin: *」を含めておけばいけまっせー!的な感じで書かれている場合が多いが、CGIとして書く場合にはもう1個だけ重要なものがあります。

    それが、

    Content-Length

    !!

    Content-Lengthが正しくないとAndroidのブラウザPCのChromeでAjax通信でレスポンスが返ってきてくれない。
    まぁ、あんまりCGIとして書くケースはないのかもしれないのですが、.htaccessを使えないときには有効かもしれません。

    Perlのコード

    大体こんな感じでJSONを返すCGIを書いたときに、「Access-Control-Allow-Origin: *」と「Content-Length」 を正確に返す必要がある。
    なので、以下コードでうまくいく。

    Ajaxアクセス用のコード

    こっちはこれだけ。
    IEを考慮していないので、XDomainRequestは無視しています。


    また、ちょっと古い記事ですが、クロスドメインなAjaxに対応したブラウザをご覧になりたい場合は、XMLHttpRequest level2に対応しているブラウザまとめをば。

    初めてのPerl 第5版
    初めてのPerl 第5版
    posted with amazlet at 12.02.15
    Randal L. Schwartz Tom Phoenix brian d foy
    オライリージャパン
    売り上げランキング: 30529

    MacOSX LionにPhoneGapをインストールしたときのメモ(2012-02-09時点) - iPhone/Android対応

    PhoneGap.png

    iPhone版

    PhoneGapもTitanium Mobile同様、結構ググると情報が古い。
    特にXCodeが3から4に上がったとこで、かなりUIも変わっているので、昔の情報はあんまり役に立たない。

    なので、PhoneGapのサイトにあるGet Started Guideを見ながらいろいろ試してみました。
    Get Started Guide « PhoneGap

    PhoneGapをダウンロードする

    Download « PhoneGapよりDownloadボタンをクリックし、PhonGapをダウンロードします。

    現時点(2012-02-07)では1.4.1のようです。
    zipファイルを解凍します。

    PhoneGapをインストールする(iOS版)

    以下のディレクトリのdmgファイルをダブルクリックします。

    /phonegap-1.4.1/lib/ios/PhoneGap-1.4.1.dmg

    すると、PhoneGap-1.4.1.pkgファイルが出現するので、次へ次へを押してインストールします。

    XCodeでPhoneGapプロジェクトを作成する

    XCodeのメニュー「File→New→New Project」を選択します。
    以下のようにPhoneGapプロジェクトを選択し、プロジェクトを作成します。

    Xcode-2.png

    "Product Name"と"Company Identifier"を入力します。
    とりあえず、僕は以下の感じでやりました。
    Company Identifierはご自分のBundle identifierを入力してくださいね。
    (ゆくゆく実機で動かすため)

    Xcode.png

    何はともあれRunさせる

    Xcode-3.png

    ↑の画像ようにiPhoneのシミュレータでRunボタンをクリックしてみたところ、
    以下のエラーが出ちゃいました。

    スクリーンショット 2012-02-07 16.15.23.png

    確かに、

    Next step is IMPORTANT! Drag the www folder into Xcode 4. You can't just drag the www folder into your app's folder. It needs to be dragged into Xcode 4!! In my case I would drag it and drop it on HiWorld shown below.


    via: Get Started Guide « PhoneGap

    と、どうやらwwwというフォルダがないからプロジェクトに追加してね的な話のようです。
    ここも、過去のPhoneGapでは、wwwフォルダがデフォルトであったりしてたようで、ググるとそっちが出てきてちょっと困ってしまいました。

    そしていろいろぐぐっているとドンピシャな記事が、

    1. XCodeの左ペインのプロジェクトのアイコンを右クリック

    2. Add files to プロジェクト名...を選択

    3. 作成したプロジェクトのフォルダの中にwwwというフォルダがあるので選択

    4. 表示されるダイアログの下の方に「Create folder references for any added folders」というのがあるので選択してAddボタンを押す

    5. XCodeの左ペインの中に青い色でwwwフォルダが表示される

    6. この状態でビルドすればSimulatorでindex.htmlの内容が表示されます


    via: [PhoneGap] PhoneGapでwwwフォルダがない | スタックスリー開発奮闘ブログ

    Xcode-1.png

    これで、wwwフォルダがXCode上に表示され、かつビルドが通るようになりました!
    (なんなんだ、このワンステップは。。。)

    スクリーンショット 2012-02-07 16.23.20.png

    実機で動かす場合

    プロビジョニングファイルの作成

    ぶっちゃけこのステップが一番面倒なんですが、やらないとダメみたいなので、やるしかないですね。
    以下の記事を順番にやっていくと、いつのまにか終わっています。
    ASCII.jp:JavaScriptでiPhoneアプリ開発!NimbleKit入門|古籏一浩のJavaScriptラボ

    そしてiPhoneをつないで、XCodeの「Window→Organizer→DEVICES」にて
    Use for Development
    をクリックすると、これまたいつの間にかiPhoneの認証が終わってる!イエス!

    iPhoneの実機での動作確認

    iPhoneが繋がっている状態なら、XCodeのシミュレータのところに自分のiPhoneの名前が出ているので、それを選択してRunするだけ。
    これで、自分のiPhoneでアプリが動き出す。


    Android版

    必要なものをセットアップ

    Android版はXCodeは使いません。
    なので、eclipseのセットアップをする必要があります。

    eclipseは3.7を使って、Mac版のAll in one eclipseはないので、以下の記事をもとに自力で作ります。
    MacでPleiades All in One Eclipse - Archit!!
    そんなに難しくないので、手順通りに行なってください。
    (All in oneを求めていない方は、eclipse単体でOKです)

    eclipse以外に以下のものが必要になりますが、これはPhoneGapでAndroidアプリを作るための基礎知識(1/3) - @ITこの記事がすごく参考になります。
    セットアップしちゃいましょう!

    1. Android SDK
    2. ADT Plugin
    3. PhoneGap(すでのiPhoneのほうでダウンロードしていますね)

    Android Projectを作成し、PhoneGapに必要なファイルを配置する

    eclipseの「File→New→Other」と選択し、Androidの配下にあるAndroid Projectを選択します。
    プロジェクトが作成されましたら、以下のようにphonegapの必要なファイルをコピーしてください。

    assetsフォルダの下にwwwフォルダを作成
    「phonegap-1.4.1/lib/android/phonegap-1.4.1.js」をコピー
    index.htmlを作成
    プロジェクト直下にlibsフォルダを作成
    「phonegap-1.4.1/lib/android/phonegap-1.4.1.jar」をコピー
    resフォルダの下にxmlフォルダを作成
    「phonegap-1.4.1/lib/android/xml/plugins.xml」をコピー

    あとは、phonegap-1.4.1.jarを右クリックしてBuild PathからAdd to Build Pathを選択します。

    最終的にこんな感じです。
    Java - phonegap_assets_www_index.html - Eclipse - _Users_hisamatsu___dev_workspace.png

    これでベースは整いました。

    Android ProjectをPhoneGap仕様にする

    AndroidManifest.xml

    ここで一点注意ですが、uses-sdk android:minSdkVersionに9と入れていますが、これは2.3.2を意味しています。
    Android SDK Managerでは2.3は2.3.3しかダウンロードできないため、ここで2.3.2を許容しておきます。
    (というかそもそもuses-sdk android:minSdkVersion書かなければいいのかな)

    src/PhonegapActivity.java

    assets/www/index.html

    phonegap-1.4.1.jsファイルはjsというフォルダの中に配置しました。

    何はともあれRunさせる

    プロジェクトを右クリックして「Run As→Android Application」を選択します。
    ちょっと時間がかかります。

    スクリーンショット 2012-02-09 14.10.07.png

    ちょっといいなと思ったのが、一度シミュレータが起動したらそのまま閉じないでおいて、
    index.htmlの修正をしても、もう一度「Run As→Android Application」をするだけです。
    これかなり速いです。
    なので、のっけのシミュレータの起動だけは結構重いですが、その後の修正点の反映は速いかもしれません。

    Androidの実機での動作確認

    Android端末の設定で、「アプリケーション→開発→USBデバックにチェックをつけるだけ。
    これで、プロジェクトを右クリックして「Run As→Android Application」を選択すると、実機側でアプリが起動する。
    簡単!

    ■関連記事
    MacOSX LionにTitanium Mobile(Studioも)をインストールしたときのメモ(2012-02-06時点) - iPhone/Android対応

    ■参考リンク
    以下のリンク先から今回の記事のヒントを大量にいただきました。
    ありがとうございます!
    PhoneGapでAndroidアプリを作るための基礎知識(1/3) - @IT
    PhoneGapを試してみる | Classmethod.dev()
    インストール方法(Android編) | PhoneGap Fan

    PhoneGap 入門ガイド (Smart Mobile Developer)
    アシアル株式会社
    翔泳社
    売り上げランキング: 225899

    過去の記事を読む

    Home

    Tag cloud
    月別アーカイブ
    Powered by
    Powered by
    Movable Type Commercial 4.261

    Page Top