KeyHoleTV開発者のブログ

日々の質問や開発の日記

iOS15によるKeyHoleTV の修正

KeyHoleTVがIOS15で動作しない

iOS15がリリースされた。 iOS14まで動作していたKeyHoleTVは、完全に動作しなくなった。KeyHoleTVを起動すると、以下のようなダイアログが表示された。

f:id:KeyHoleTV:20220101124152p:plain

iOS15でアプリが動作しなくなった

これらは、利用者から報告を受けたので、手持ちのiPhoneをiOS15にアップグレードして、XCode10で再コンパイルして動作させてみた。 同じダイアログが表示され動作しない。

XCodeのアップデートとMacOSのアップデートとMacの不具合

iOS15用のXCodeは、XCode13が必要で、XCode13は、MacOS 11.6 (BIg Sur)にしないといけない。 そこで、ます使っているMacMiniのOSを11.6にアップグレードし、その後、XCode13をインストールした。

XCode13を起動して、KeyHoleTVのXCodeのプロジェクトファイルを読み込ませてみると、すんなり読み込んで開発環境が整った。 

デバックするためには、シミュレータを動作させる。 シミュレータは、XCodeのホタン一つで起動するので、起動して動作確認を行うと、シミュレータが起動せず、Macが落ちて再起動がかかる。何度やっても結果は同じ。 一応Macのセーフモードを起動してみた。 また、機器の動作確認を行うことができるので、それもやった見た。 特に問題は報告されない。 しかし、XCodeでシミュレータを動作させると、Macが落ちて再起動がかかる。 ここで、一応XCodeのバグ報告で現象をAppleに報告した。

KeyHoleTVが動作しない原因

シミュレータが動作しないので、手持ちのiPhoneで動作確認を行うことにした。 プログラムを実行させてみると、iPhoneのCPU消費が異常に増えていることが分かった。そして、プログラムが異常終了する。 iPhoneのアプリは、アプリが異常終了すると、main に戻ってどこで異常したかがよくわからない場合ある。少なくとも、KeyHoleTVのコードではなく、iOSのライブラリで異常終了している。

KeyHoleTVは、画面遷移のために、iOSのライブラリでUINavigationContoller, UIViewControllerを利用している。 KeyHoleTVは利用者名が登録されていない状態では、画面遷移して「既存の利用者名」と「利用者登録」のボタンを表示するUIViewControllerの画面に飛ぶ。 そこで、この画面に飛ぶ処理にブレークポイントを設置して動作させてみた。

すると、画面遷移をするライブラリメッソド(pushViewController:animated:)が画面遷移せず、何度も呼び出されていることが分かった。

KeyHoleTVはタイマーのメソッドを利用して、画面遷移の状態を管理する値により処理をする仕掛けを用いているからで、遷移した後、状態を変更して再び、遷移しないようしていた。 この仕掛けは、利用者名の入力やパスワードの入力をすると、ログインボタンが有効になるような処理を行っている。

iOS14までは、遷移をさせると、viewWillAppear: や viewDidAppear:のメソッドが呼び出されていた。KeyHoleTVは、viewWillAppearの処理の中で、遷移の状態の値を変更していた。 何度も画面遷移を呼び出していることから、viewWillAppearが呼び出されないことが判明した。 そこで、iOS開発のドキュメントを調べてみると、

developer.apple.com

Note

If a view controller is presented by a view controller inside of a popover, this method is not invoked on the presenting view controller after the presented controller is dismissed.

となっていた。 元の UIView Controller は閉じていないが、viewWillAppearが呼び出されない。 理由はわからないが、呼び出されないので、画面遷移のライブラリメッソドを呼び出した後で、画面の状態を管理する値を変更してみた。 すると、画面遷移が行われた。

画面遷移が行われたが、ボタンの表示が無茶苦茶になった。KeyHoleTVは、viewDidAppearで画面上のボタンの配置を行っているからで、viewDidAppearが呼ばれない状況では、正しく画面の配置がなされていない。 ここで、しばらくハマった。画面遷移が行われる直前に画面の内容を変更したいが、うまく行かない。 ここで、色々試してみたが殆どがうまく行かない。

Mac MINi SSDの問題発生

何度もプログラムを作りデバックしていたが、突然XCodeでコンパイルの最中にMacが落ちて再起動するようになった。 何度もハードウェアのチェックを行ったが、エラーは見られない。 セーフモードで起動した時だけうまく動作する。しかし、セーフモードで起動すると、iPhoneとの接続でデバッグが出来ない場合があった。 当然シミュレータは立ち上がらない。

遂にAppleにコンタクトを取って状況を説明してみたが、彼らは、私が出した不具合の報告を読んでおり、解決策が見つけられない。 

そこで、フット気がついたことがあった。 Mac Miniは、SSDう。を使っている。SSDは、USBメモリと同様で書き込み回数に制限がある。例え使用したファイルなどがディスクの容量未満であっても、一度書き込んだデータは、絶対に消えず、消したというフラグが立つだけ。更にディスク管理のアプリは、どのくらいSSDの有効領域があるかを教えてくれないし、システムチェックでも引っかからない。

XCodeは、コンパイルしたデータを一旦保存しそれらをリンクする。この作業を繰り返し行うとSSDの寿命が減少する。 おそらく、これが原因でMacが落ちたりするのであろうと想定して、外付けのハードディスクを購入した。 外付けのハードディスクが当着した後、バックアップを取ったり、起動ディスクを構築したり、ホームフォルダを外付けディスクに移動した。 これらの作業の結果、XCodeでシミュレータが起動するようになり、Macも落ちなくなった。

viewDidLayoutSubviewsによる解決

開発ドキュメントを色々読んで見た結果、viewDidLayoutSubviewsが使えるかも知れないと思い、プログラムを実装した。 この結果pushViewController:animated で遷移した時は、一度だけ呼び出されることが分かった。また、デバイスが移転した時も呼び出される。 これは、AutoLayout と呼ばれる機構が実装されたからで、ストーリボードを使った場合、UIViewControllerに配置する部品の位置を関節的に設定でき、デバイスの大きさが変わっても、相対的にボタンなどがうまく配置される。 しかし、KeyHoleTV

は、ストーリボードを利用していないので、プログラムで設定する必要がある。 最初は、自動レイアウトするようにプログラムを記述したが全く動作しない。おそらく何らかの初期状態の設定が必要だと思う。