View階層をダンプする
今までいろいろなGUIツールキットを触ってきたが、必ず一度はコンテキストのビュー階層を列挙するコードを書いてみる。
iOSの場合、これを行うのはUIViewControllerのコンテキストであることが多いと思うが、その場合プロパティviewでルートのビューの参照が取得できるので、これを基点にビューをトラバースするコードを書けば良い。
dumpAllChildrenOfViewメソッド
-(void) dumpAllChildrenOfView:(UIView*) view depth:(int) d buffer:(NSMutableString*) b { NSString *str = @""; for (int i = 0; i < d; i++) { str = [str stringByAppendingFormat: @" "]; } str = [str stringByAppendingFormat: @"%@%@\n", str, view.class]; [b appendString: str]; d++; for (UIView *child in [view subviews]) { //recursive call [self dumpAllChildrenOfView:child depth: d buffer: b]; } }
こんな感じで。あとはViewControllerのコンテキストで呼び出せば良い。
テストには今回もHonepwnerプロジェクトの詳細ビューを使い、ツールバーボタンのIBActionで上記メソッドを呼び出すように、XcodeでIBActionを構成した。
enumerateViewAction メソッド (IBAction)
- (IBAction)enumerateViewAction:(id)sender { NSMutableString* ms = [[NSMutableString alloc] init]; [self dumpAllChildrenOfView:[self view] depth:1 buffer:ms]; UIAlertView* al; @try { al = [[UIAlertView alloc] initWithTitle: @"" message: ms delegate: nil cancelButtonTitle: @"OK" otherButtonTitles:nil]; [al show]; } @finally { [al release]; NSLog(@"\n%@", ms); [ms release]; } }
実行結果
同メソッドはダイアログに表示する他にNSLogの出力も行っている。
2012-01-20 21:10:36.205 Homwpwner[314:f803] UIView UILabel UITextField UITextFieldRoundedRectBackgroundView UIImageView UIImageView UIImageView UITextFieldLabel UILabel UITextField UITextFieldRoundedRectBackgroundView UIImageView UIImageView UIImageView UITextFieldLabel UILabel UITextField UITextFieldRoundedRectBackgroundView UIImageView UIImageView UIImageView UITextFieldLabel UILabel UIImageView UIToolbar _UIToolbarBackground UIToolbarButton UIButton UIImageView UIImageView UIButtonLabel UIToolbarButton UIButton UIImageView UIImageView UIButtonLabel
これは興味深い。
例えば、プリミティブに見えていたUIButtonクラスもUIImageViewとUIButtonLabelのコンポジションで構成されている。
iOS UIKitにおけるViewの階層は実際にxib上で見えているビューだけで構成されている訳では無いことが分る。