MonoTouch開発でiPhoneの画面が真っ暗になる症状 −解決編−
iPhoneにデフォルトであるカレンダーと同じ外観のビューを作成していました.カレンダーを何度かアニメーションでスライド表示すると画面が真っ黒になってしまう症状が生じてその原因が分からずに困っていました.
その原因はApplicationDelegateでUIWindowのインスタンスを保持していなかったためだったようです.
このようにメソッドでインスタンスを作成しただけではだめで:
[Register("someDelegate")] public class someDelegate: UIApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { var win = new UIWindow(UIScreen.MainScreen.Bounds); .... } }
インスタンス変数として保持すればちゃんと動きます.
[Register("someDelegate")] public class someDelegate: UIApplicationDelegate { UIWindow _window; public override bool FinishedLaunching(UIApplication app, NSDictionary options) { _window = new UIWindow(UIScreen.MainScreen.Bounds); .... } }
Delegateのインスタンスから参照されていないUIWindowが適当なタイミングで解放されてしまったのかもしれません.その解放がタイマーで周期的に行うのではなくて,UIの操作を何度か行ったときに行うものであれば,今回の振る舞いも理解できます.
症状として,例外も何も飛んでこないし,UIのメッセージループは動いたままだし,デバッガで処理を終えないしで原因が分からず,かなり悩みました.UIのライブラリが根っこから.netであれば不用意なメモリ解放もなかったのかもしれません.全て1からコードを書いていたからこれが生じましたが,普通にInterfaceBuilderを使っていれば遭遇しない現象ではあります.
MonoTouchのUIViewはObjective-Cのランタイムライブラリが管理しているUIViewの単なるラッパーで,このUIViewはUIWindowがViewに設定されたときにretainされているから保持されているはず,そう思っていたのですが何かが違うようです.
UIWindowが保持されていれば,そこから参照されているUIViewのインスタンスが開放されることはないとは思うのですが,念のために,Objective-Cのライブラリに関わる境界部分では,全てのリソースは可能な限りインスタンス変数に保持しようと思いました.