Fast App Switching(iOSマルチタスク)の設定
iOS4以降で実装されているFast App Switchingを無効にするやり方。
一度ホームボタン押下等でアプリをバックグランドにやったあとに
再度アプリを開くと前回の状態で復帰できる機能ですが、
アプリによっては無効にしたいこともあると思います。
設定は簡単で
info.plistに[Application does not run in background]
というキーを追加してYESにすればOK。
iPhoneシミュレータのスクリーンショット
いつもど忘れするのでメモ。
キーボードで[command]+[shift]+[4]を同時に押しながら、[space]キーを押す。
カメラアイコンが表示されるので、
iPhoneシミュレータの画面を選択してクリックする。
これでデスクトップにスクリーンショットがPNG形式で保存されます。
UIViewとlayerの違い
複数の画像を表示するようなアプリの時に、UIImageを使ってるパターンと
親viewのlayerにsublayer使って実装してるパターンがあったりして、
どういう理由で使い分けているのか自分自身あまり理解できていませんでした。
view自体がlayerプロパティを持っていて、
そいつがviewの描画を担当しているってのは
公式のリファレンスなんかを読んで納得したんだけど、
じゃあviewに出来てlayer単体に出来ないことってなに?
(もしくはその逆)って部分がイマイチすっきりしていなくて。
決定的に違うのはlayer単体はタッチ等のイベントを拾わない事。
(UIResponderのサブクラスではない)
つまり、大量の画像を単純に表示のみするようなケースでは
layerを親viewのlayerにsublayerした方がよいのだと思います。
逆に、大量の画像を全てUIImage等にしてしまうと
レスポンダチェーンが発生して処理としては重くなるのだと思います。
実際にどの程度負荷がかかるのかは未検証なので推測ですけど。。。
deallocとviewDidUnLoadについて
若干前回の話題と前後するが引き続きメモリ管理の話です。
iPhoneアプリ開発の書籍等では、
説明を簡略化する目的と思われるがメモリ管理について、
最低限のコードしか書いていないケースがあります。
viewDidUnLoadについては結構無視されている事があるみたいだけど、
実際に公開するアプリを作る時は意識しないと
メモリリークで悩まされる事になりそう。
大体どこでもdeallocはインスタンス変数等、
retainしたものはここで解放しなければいけないってとこまでは書いてあるけど
viewDidUnLoadでもちゃんと解放処理を行う必要があります。
viewDidLoadでインスタンス変数の初期化(UIパーツの生成等)
を行うケースが多いと思うが、
ここで初期化している変数をviewDidUnLoadで解放します。
initで初期化している変数はviewDidUnLoadで解放してしまうと
再度viewDidLoadが呼ばれても読み込まれないのでdeallocでのみ解放します。
・すべてのインスタンス変数 ⇒ deallocで解放
・viewDidLoadで初期化する変数 ⇒ viewDidUnLoadとdeallocで解放。
ちなみに、viewDidUnLoadで解放する時は
[hoge release] の後に hoge = nil;
としておく。
こうすれば、viewDidUnLoadが呼ばれた後にdeallocが呼ばれても、
nilに対するreleaseが行われるだけ
(objective-cはnilにメッセージを送っても何も起こらない)
になりエラーとはなりません。
UIViewControllerのloadViewとviewDidLoadの使い分け
基本的にコードベースで(InterfaceBuilderを使わずに)構築している前提での話。。。
親view(この場合はViewControllerのview)へsubviewの追加を行う場合、
loadViewとviewDidLoadのどちらで書くべきか、書籍等でも記述が分かれているので
悩んでいたのですが、自分なりの解釈というか考え方をまとめました。
公式リファレンス(ViewControllerPGforiPhoneOS)によると、
ViewControllerのview管理は大きく
ロードサイクルとアンロードサイクルという独立した
サイクルで行われているとのこと。
ロードサイクルは
アプリからviewを要求された時にviewがまだ存在しない場合発生する。
アンロードサイクルは
アプリケーションがメモリ不足の警告を受けると発生する。
ロードサイクル:
1.viewプロパティにviewが設定されていない場合、loadViewを呼び出す。
1-1.loadViewをオーバーライドした場合
loadViewの実装中でviewプロパティにnil以外をプログラマが設定する必要がある。
1-2.loadViewをオーバーライドしない場合
ViewControllerのnibNameプロパティとnibBundleプロパティを使用して、
指定のnibファイルからビューをロードしようとする。
上記の処理でビューが見つからない場合、
ViewControllerの名前と同名のnibファイルを検索、そのファイルをロードする。
該当するnibファイルが見つからなければ、
メソッドは空のUIViewオブジェクトを作成して、viewプロパティに代入する。
2.viewDidLoadを呼び出す。(ロード時に必要な付加処理を行う。)
アンロードサイクル:
1.アプリケーションがシステムからメモリ不足の警告を受け取る。
2.ViewControllerはdidReceiveMemoryWarningを呼び出す。
ビューを解放しても安全だと判断された場合のみ、ビューが解放される。
3.ViewControllerはビューを解放するとviewDidUnLoadを呼び出す。
このメソッドをオーバーライドすることで使用していたオブジェクトを
解放する事が出来る。
リファレンスによると大きくこのような流れらしいです。
つまり、loadViewはあくまでViewControllerのviewプロパティを
間違いなくnil以外にするための処理で、
コードベースでviewを作成する場合はここでそのviewを作成する。
その他の初期化処理はviewDidLoadでするのが想定されている動き(だと思う。)
実際はloadViewとviewDidLoadは一連の流れで
呼び出されるようなのでどちらに書いても動きはする。
ただし,loadVIewをオーバーライドし、
実装中で[super loadView]もコールせず self.view 等とするとエラーになる。
(viewプロパティに値が未設定状態のため。)
ただ、アンロードサイクルを見ると、メモリが不足した際にアプリは
didReceiveMemoryWarningを呼び出し、
ビュー解放時にはviewDidUnLoadをコールする。
解放される範囲はviewDidLoadで作成したオブジェクトに限定される。
つまり、loadViewで作成したオブジェクトは範囲外となる。
長くなりましたが、この辺りを考慮すると
subviewの作成はviewDidLoadで行った方が良いという事ですかね。