このエントリーをはてなブックマークに追加このエントリをつぶやく

消えたUIButton

ユーザインタフェースは重要ですよね。
iPhoneがここまで広く支持されたのも、フリックやピンチといった独特の入力操作、それを視覚的にフィードバックするアニメーション効果によるところが大きいのではないでしょうか。
当然、これは我々アプリ開発者にも求められます。
Interface Builderでボタンやラベルを配置しておしまいではなく、タッチイベントに合わせて動的にUIを制御する必要が出てきます。
かくして、配置したはずのUIButtonが画面に現れない状況に遭遇するのです。

在りし日のボタン4


さまざまな原因が考えられます。それはもううんざりするほど。

  • 表示する座標が間違っている
  • hiddenプロパティをセットしている
  • アフィン変換が何かおかしなことになっている
  • 別のビューに隠れている
  • 親ビューのクリップ領域外にある
  • 背景色や画像等の設定ミスで親ビューの色と同化している
  • そもそもビュー階層に正しく登録できていない
  • etc.

layerプロパティでCALayerに対して装飾を施していれば、そっちも疑わなければなりません。
ソースコードとにらめっこして、可能性をひとつずつ否定していくのは大変な作業です。

UIViewには便利な非公開APIが用意されています。
[cc lang=”objc”]
– (NSString *)recursiveDescription;
[/cc]
名前から想像がつくように、対象のビューとその下位にあるすべてのサブビューをまとめて表現する文字列を返します。これを任意の場所で呼び出してコンソールに出力すれば、その時点でのビュー階層が一目で把握できるという寸法です。

実際に試してみましょう。
今回は画面をタップしたタイミングでビューの状態を出力させることにします。
問題が起きているUIViewControllerのサブクラスに次のコードを追加します。
[cc lang=”objc”]
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@”%@”, [self.view recursiveDescription]);
}
[/cc]
警告が出ますが、綴りを間違えていなければ大丈夫です。
実行して画面のどこかをタップすると、コンソールには以下のように出力されます。
ちなみに、ボタンはすべてUIButtonクラスで生成していますが、舞台裏では見たことのないクラスが使われているようです。

出力結果

さて、下から三行分が消えたUIButtonにあたります。
おわかりでしょうか?
UIButtonの上位にあるUIViewのalphaプロパティが0になっています。
親ビューが透明なので、その下位ビューも一緒に消えていたというオチでした。
UIButton自体には何の問題もないため、デバッグの進め方によっては盛大にハマる可能性があります。

UIKitは非常に強力なフレームワークですが、多機能であるがゆえにデバッグも一筋縄ではいかないケースが多く、開発経験が一年を超えた今でも苦労しています。
この記事が皆様のデバッグのお役に立てますように。

あ、そうそう。
あくまで非公開APIなので、デバッグが済んだら消しておくことをお忘れなく!

カテゴリー: プログラミング   タグ: ,   この投稿のパーマリンク

コメントは受け付けていません。