It's often helpful to take a look at your UIView hierarchy; and when I say "look", I mean all the way down. You can just as easily look at the component subviews that comprise on-screen objects like buttons, switches, and sliders, as you can at the UIImageViews and UIButtons that you add directly to your screen. UIButtons, for example, are composed of three image views and a label. Some UITextFields are built on a private UITextFieldRoundedRectBackgroundView, with a number of UIImageViews that are added below that class.
You can easily dive down and explore your entire user interface by adding some simple routines to your application delegate. In the following sample code, I wait for my window to build and display itself and then call my showViewsexplode: level: routine. By starting at the main window, I can see every single subview that appears on-screen. My routine iterates through each subview and calls itself recursively, each time adding a greater indention so you can see at a glance the relative parenting for each view.
void doLog(int level, id formatstring,...)
{
int i;
for (i = 0; i < level; i++) printf(" ");
va_list arglist;
if (formatstring)
{
va_start(arglist, formatstring);
id outstring = [[NSString alloc] initWithFormat:formatstring arguments:arglist];
fprintf(stderr, "%s\n", [outstring UTF8String]);
va_end(arglist);
}
}
@interface ConverterAppDelegate : NSObject <UIApplicationDelegate>
@end
@implementation ConverterAppDelegate
- (void) explode: (id) aView level: (int) level
{
doLog(level, @"%@", [[aView class] description]);
doLog(level, @"%@", NSStringFromCGRect([aView frame]));
for (UIView *subview in [aView subviews])
[self explode:subview level:(level + 1)];
}
- (void) showViews
{
[self explode:[[UIApplication sharedApplication] keyWindow] level:0];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ConverterController *cc = [ConverterController sharedInstance];
[window addSubview:cc.view];
[window makeKeyAndVisible];
[self performSelector:@selector(showViews) withObject:NULL afterDelay:2.0f];
}
@end
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"ConverterAppDelegate");
[pool release];
return retVal;
}
Because the iPhone does not distinguish between subviews created by a program and subviews added by Apple, this code can move down into detail usually hidden by the SDK and reveal both the structure of those SDK-provided items as well as the underlying classes that you may want to access. Here, you see how my Converter utility is built from my own classes, from Apple standard components, and from the subviews of those components which are normally not revealed.
Next week, I'll show you how to identify, tag and retrieve these subviews at will. For now, here's a peek at what my Converter utility looked like after being exploded from the top down:
UIWindow
{{0, 0}, {320, 480}}
MultiSlideView
{{0, 20}, {320, 460}}
AdMobViewInternal
{{0, 412}, {320, 48}}
UIScrollView
{{0, 0}, {320, 410}}
CPageView
{{0, 0}, {320, 360}}
UIImageView
{{130.5, 135.5}, {59, 29}}
UILabel
{{80, 25}, {160, 40}}
UIButton
{{80, 25}, {160, 40}}
UIImageView
{{0, 0}, {160, 40}}
UIImageView
{{30, -30}, {100, 100}}
UIImageView
{{0, 0}, {0, 0}}
UILabel
{{0, 0}, {0, 0}}
UILabel
{{50, 100}, {220, 40}}
UIButton
{{50, 100}, {220, 40}}
UIImageView
{{0, 0}, {220, 40}}
UIImageView
{{60, -30}, {100, 100}}
UIImageView
{{0, 0}, {0, 0}}
UILabel
{{0, 0}, {0, 0}}
UITextField
{{40, 70}, {240, 40}}
UITextFieldRoundedRectBackgroundView
{{0, 0}, {240, 40}}
UIImageView
{{0, 0}, {8, 15}}
UIImageView
{{8, 0}, {224, 15}}
UIImageView
{{232, 0}, {8, 15}}
UIImageView
{{8, 0}, {0, 15}}
UIImageView
{{0, 15}, {8, 10}}
UIImageView
{{8, 15}, {224, 10}}
UIImageView
{{232, 15}, {8, 10}}
UIImageView
{{8, 15}, {0, 10}}
UIImageView
{{0, 25}, {8, 15}}
UIImageView
{{8, 25}, {224, 15}}
UIImageView
{{232, 25}, {8, 15}}
UIImageView
{{8, 25}, {0, 15}}
UILabel
{{7, 2}, {226, 31}}
UILabel
{{80, 235}, {160, 40}}
UIButton
{{80, 235}, {160, 40}}
UIImageView
{{0, 0}, {160, 40}}
UIImageView
{{30, -30}, {100, 100}}
UIImageView
{{0, 0}, {0, 0}}
UILabel
{{0, 0}, {0, 0}}
UILabel
{{50, 155}, {220, 40}}
UIButton
{{50, 155}, {220, 40}}
UIImageView
{{0, 0}, {220, 40}}
UIImageView
{{60, -30}, {100, 100}}
UIImageView
{{0, 0}, {0, 0}}
UILabel
{{0, 0}, {0, 0}}
UITextField
{{40, 190}, {240, 40}}
UITextFieldRoundedRectBackgroundView
{{0, 0}, {240, 40}}
UIImageView
{{0, 0}, {8, 15}}
UIImageView
{{8, 0}, {224, 15}}
UIImageView
{{232, 0}, {8, 15}}
UIImageView
{{8, 0}, {0, 15}}
UIImageView
{{0, 15}, {8, 10}}
UIImageView
{{8, 15}, {224, 10}}
UIImageView
{{232, 15}, {8, 10}}
UIImageView
{{8, 15}, {0, 10}}
UIImageView
{{0, 25}, {8, 15}}
UIImageView
{{8, 25}, {224, 15}}
UIImageView
{{232, 25}, {8, 15}}
UIImageView
{{8, 25}, {0, 15}}
UILabel
{{7, 2}, {226, 31}}
UIButton
{{280, 0}, {40, 40}}
UIImageView
{{0, 0}, {40, 40}}
UIImageView
{{-30, -30.5}, {100, 100}}
UIImageView
{{11, 10}, {18, 19}}
UILabel
{{0, 0}, {0, 0}}
UIPageControl
{{20, 360}, {280, 40}}
UIImageView
{{137, 17}, {6, 6}}
UIButton
{{10.5, 365.5}, {29, 29}}
UIImageView
{{0, 0}, {29, 29}}
UIImageView
{{0, 0}, {0, 0}}
UILabel
{{0, 0}, {0, 0}}
UIButton
{{275, 360}, {40, 40}}
UIImageView
{{0, 0}, {40, 40}}
UIImageView
{{5, 5}, {29, 29}}
UILabel
{{0, 0}, {0, 0}}
Leave a comment