Interface Builder是建立视图层次的最便利工具,因为它可以让您看到视图在运行时的外观。在界面制作完成后,它将视图对象及其层次关系保存在nib文件中。在运行时,系统会按照nib文件的内容为应用程序重新创建那些对象和关系。当一个nib文件被装载时,系统会自动调用重建视图层次所需要的UIView方法。
如果您不喜欢通过Interface Builder和nib文件来创建视图层次,则可以通过代码来创建。如果一个视图必须具有某些子视图才能工作,则应该在其initWithFrame:方法中进行对其创建,以确保子视图可以和视图一起被显示和初始化。如果子视图是应用程序设计的一部分(而不是视图工作必需的),则应该在视图的初始化代码之外进行创建。在iPhone程序中,有两个地方最常用于创建视图和子视图,它们是应用程序委托对象的applicationDidFinishLaunching:方法和视图控制器的loadView方法。
您可以通过下面的方法来操作视图层次中的视图对象:
▪调用父视图的addSubview:方法来添加视图,该方法将一个视图添加到子视图列表的最后。
▪调用父视图的insertSubview:...方法可以在父视图的子视图列表中间插入视图。
▪调用父视图的bringSubviewToFront:、sendSubviewToBack:、或exchangeSubviewAtIndex:withSubviewAtIndex:方法可以对父视图的子视图进行重新排序。使用这些方法比从父视图中移除子视图并再次插入要快一些。
▪调用子视图(而不是父视图)的removeFromSuperview方法可以将子视图从父视图中移除。
在添加子视图时,UIKit会根据子视图的当前边框矩形确定其在父视图中的初始位置。您可以随时通过修改子视图的frame属性声明来改变其位置。缺省情况下,边框位于父视图可视边界外部的子视图不会被裁剪。如果您希望激活裁剪功能,必须将父视图的clipsToBounds属性设置为YES。
程序清单显示了一个应用程序委托对象的applicationDidFinishLaunching:方法示例。在这个例子中,应用程序委托在启动时通过代码创建全部的用户界面。界面中包含两个普通的UIView对象,用于显示基本颜色。每个视图都被嵌入到窗口中,窗口也是UIView 的一个子类,因此可以作为父视图。父视图会保持它们的子视图,因此这个方法释放了新创建的视图对象,以避免重复保持。
程序清单 创建一个带有视图的窗口
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Create the window object and assign it to the
// window instance variable of the application delegate.
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.backgroundColor = [UIColor whiteColor];
// Create a simple red square
CGRect redFrame = CGRectMake(10, 10, 100, 100);
UIView *redView = [[UIView alloc] initWithFrame:redFrame];
redView.backgroundColor = [UIColor redColor];
// Create a simple blue square
CGRect blueFrame = CGRectMake(10, 150, 100, 100);
UIView *blueView = [[UIView alloc] initWithFrame:blueFrame];
blueView.backgroundColor = [UIColor blueColor];
// Add the square views to the window
[window addSubview:redView];
[window addSubview:blueView];
// Once added to the window, release the views to avoid the
// extra retain count on each of them.
[redView release];
[blueView release];
// Show the window.
[window makeKeyAndVisible];
}
重要提示:在内存管理方面,可以将子视图考虑为其它的集合对象。特别是当您通过addSubview:方法将一个视图作为子视图插入时,父视图会对其进行保持操作。反过来,当您通过removeFromSuperview方法将子视图从父视图移走时,子视图会被自动释放。在将视图加入视图层次之后释放该对象可以避免多余的保持操作,从而避免内存泄露。
当您为某个视图添加子视图时,UIKit会向相应的父子视图发送几个消息,通知它们当前发生的状态变化。您可以在自己的定制视图中对诸如willMoveToSuperview:、willMoveToWindow:、willRemoveSubview:、didAddSubview:、didMoveToSuperview、和didMoveToWindow这样的方法进行重载,以便在事件发生的前后进行必要的处理,并根据发生的变化更新视图的状态信息。
在视图层次建立之后,您可以通过视图的superview属性来取得其父视图,或者通过subviews属性取得视图的子视图。您也可以通过isDescendantOfView:方法来判定一个视图是否在其父视图的视图层中。一个视图层次的根视图没有父视图,因此其superview属性被设置为nil。对于当前被显示在屏幕上的视图,窗口对象通常是整个视图层次的根视图。
如果您不喜欢通过Interface Builder和nib文件来创建视图层次,则可以通过代码来创建。如果一个视图必须具有某些子视图才能工作,则应该在其initWithFrame:方法中进行对其创建,以确保子视图可以和视图一起被显示和初始化。如果子视图是应用程序设计的一部分(而不是视图工作必需的),则应该在视图的初始化代码之外进行创建。在iPhone程序中,有两个地方最常用于创建视图和子视图,它们是应用程序委托对象的applicationDidFinishLaunching:方法和视图控制器的loadView方法。
您可以通过下面的方法来操作视图层次中的视图对象:
▪调用父视图的addSubview:方法来添加视图,该方法将一个视图添加到子视图列表的最后。
▪调用父视图的insertSubview:...方法可以在父视图的子视图列表中间插入视图。
▪调用父视图的bringSubviewToFront:、sendSubviewToBack:、或exchangeSubviewAtIndex:withSubviewAtIndex:方法可以对父视图的子视图进行重新排序。使用这些方法比从父视图中移除子视图并再次插入要快一些。
▪调用子视图(而不是父视图)的removeFromSuperview方法可以将子视图从父视图中移除。
在添加子视图时,UIKit会根据子视图的当前边框矩形确定其在父视图中的初始位置。您可以随时通过修改子视图的frame属性声明来改变其位置。缺省情况下,边框位于父视图可视边界外部的子视图不会被裁剪。如果您希望激活裁剪功能,必须将父视图的clipsToBounds属性设置为YES。
程序清单显示了一个应用程序委托对象的applicationDidFinishLaunching:方法示例。在这个例子中,应用程序委托在启动时通过代码创建全部的用户界面。界面中包含两个普通的UIView对象,用于显示基本颜色。每个视图都被嵌入到窗口中,窗口也是UIView 的一个子类,因此可以作为父视图。父视图会保持它们的子视图,因此这个方法释放了新创建的视图对象,以避免重复保持。
程序清单 创建一个带有视图的窗口
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Create the window object and assign it to the
// window instance variable of the application delegate.
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.backgroundColor = [UIColor whiteColor];
// Create a simple red square
CGRect redFrame = CGRectMake(10, 10, 100, 100);
UIView *redView = [[UIView alloc] initWithFrame:redFrame];
redView.backgroundColor = [UIColor redColor];
// Create a simple blue square
CGRect blueFrame = CGRectMake(10, 150, 100, 100);
UIView *blueView = [[UIView alloc] initWithFrame:blueFrame];
blueView.backgroundColor = [UIColor blueColor];
// Add the square views to the window
[window addSubview:redView];
[window addSubview:blueView];
// Once added to the window, release the views to avoid the
// extra retain count on each of them.
[redView release];
[blueView release];
// Show the window.
[window makeKeyAndVisible];
}
重要提示:在内存管理方面,可以将子视图考虑为其它的集合对象。特别是当您通过addSubview:方法将一个视图作为子视图插入时,父视图会对其进行保持操作。反过来,当您通过removeFromSuperview方法将子视图从父视图移走时,子视图会被自动释放。在将视图加入视图层次之后释放该对象可以避免多余的保持操作,从而避免内存泄露。
当您为某个视图添加子视图时,UIKit会向相应的父子视图发送几个消息,通知它们当前发生的状态变化。您可以在自己的定制视图中对诸如willMoveToSuperview:、willMoveToWindow:、willRemoveSubview:、didAddSubview:、didMoveToSuperview、和didMoveToWindow这样的方法进行重载,以便在事件发生的前后进行必要的处理,并根据发生的变化更新视图的状态信息。
在视图层次建立之后,您可以通过视图的superview属性来取得其父视图,或者通过subviews属性取得视图的子视图。您也可以通过isDescendantOfView:方法来判定一个视图是否在其父视图的视图层中。一个视图层次的根视图没有父视图,因此其superview属性被设置为nil。对于当前被显示在屏幕上的视图,窗口对象通常是整个视图层次的根视图。
您可以通过视图的window属性来取得指向其父窗口(如果有的话)的指针,如果视图还没有被链接到窗口上,则该属性会被设置为nil。
//一个很简便直接的方法,一句代码移除所有子视图
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];