http://www.2cto.com/kf/201202/120864.html
使用Xcode4以前的版本进行iPhone开发,新建Window-based Application类型的工程时,都会自动生成MainWindow.xib,并且都至少包含一个UIApplicationDelegate和一个UIWindow对象。
但是Xcode4以后,新建工程时,工程template这一块有很大改动,没有Window-based Application这一项了,但是有个Empty Application(iOS->Application下),现在描述以这种方式新建工程,然后自已创建MainWindow.xib并使用,和不用MainWindow.xib两种实现。
另外多视图实现采用三个UIViewController来实现,一个FirstViewController使用FirstView.xib设计界面,上面一个按钮点后切找到SecondViewController的界面,一个SecondViewController使用SecondView.xib设计界面,上面也有一个按钮点后切换到FirstViewController,一个SwitchViewController负责这两个controller的界面的切换,SwitchViewController作为rootViewController,如果一个应用没有rootViewController启动就会报错“Applications are expected to have a root view controller at the end of application launch”,其实上面两种方式就是:
第一种:创建MainWindow.xib,默认有window,需要手动添加delegate指定所属类为MVTestAppDelegate,添加UIViewController,指定所属类为SwitchViewController,然后在委托MVTestAppDelegate代码中[windowaddSubview:viewController.view];将该controller的view添加到window。不需要再使用代码来创建和初始化应用委托的window和controller的view了,这些都通过MainWindow.xib来做了。下面第二种方式就是这部分不通过MainWindow.xib来做,而是通过代码实现就用delegate的window和controller的创建和初始化
第二种:即上面第一种方式中MainWindow.xib实现的工作通过Delegate中代码来实现。详细如下:
CMD+SHIFT+N打开新建工程窗口,选择Empty Application这一项(会默认提供一个delegate和一个window),取名为MVTest。如下图:
新建SwitchViewController继承UIViewController,去掉with XIB for user interface,
同SwitchViewController一样,新建FirstViewController,和SecondViewController,然后新建FirstView.xib和Second.xib,如下图:
两个xib上面分别都添加一个label和一个button,如下图:
接下来在MVTestAppDelegate头文件中添加:
@property (nonatomic, retain)SwitchViewController *viewController;// 注意:window和viewController前面的IBOutlet
+(MVTestAppDelegate *)App;
并且在*.m文件中实现,如下图:
另外,SwitchViewController.h:
#import <UIKit/UIKit.h>
@classFirstViewController;
@classSecondViewController;
@interface SwitchViewController :UIViewController {
FirstViewController* firstviewcontroller;
SecondViewController* secondviewcontroller;
}
@property (nonatomic,retain)FirstViewController* firstviewcontroller;
@property (nonatomic,retain)SecondViewController* secondviewcontroller;
-(void)initView;
-(void)showFirstView;
-(void)showSecondView;
-(void)removeAllView;
@end
SwitchViewController.m:
#import "SwitchViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
@implementation SwitchViewController
@synthesize firstviewcontroller;
@synthesize secondviewcontroller;
-(void)initView{
NSLog(@"ttt");
if(self.firstviewcontroller ==nil){
self.firstviewcontroller = [[FirstViewControlleralloc]initWithNibName:@"FirstView"bundle:nil];
}
[selfremoveAllView];
[self.viewinsertSubview:self.firstviewcontroller.viewatIndex:0];
}
-(void)showFirstView{
if(self.firstviewcontroller ==nil){
self.firstviewcontroller = [[FirstViewControlleralloc]initWithNibName:@"FirstView"bundle:nil];
}
[selfremoveAllView];
[self.viewinsertSubview:self.firstviewcontroller.viewatIndex:0];
}
-(void)showSecondView{
if(self.secondviewcontroller ==nil){
self.secondviewcontroller = [[SecondViewControlleralloc]initWithNibName:@"SecondView"bundle:nil];
}
[selfremoveAllView];
[self.viewinsertSubview:self.secondviewcontroller.viewatIndex:0];
}
-(void)removeAllView{
for(NSInteger i=0;i<[self.view.subviewscount];i++){
[[self.view.subviewsobjectAtIndex:i]removeFromSuperview];
}
}
@end
在这两个controller,FirstViewController和SecondViewController里面,均分别添加-(IBAction)buttonClick:(id)sender;,并实现:
-(IBAction)buttonClick:(id)sender{
[[MVTestAppDelegateApp].viewControllershowSecondView]; //FirstViewController调用这个showSecondView,SecondViewController里面调用showFirstView.
}
然后分别指定FirstView.xib的File's Owner所属类为FirstViewController,SecondView.xib的所属类为SecondViewController,并将xib界面上的按钮与IBAction连接,同时将Outlets下面的view与界面的view连接。如下图:
接下来涉及到MainWindow.xib了:
一、不用MainWindow.xib
(1) 初始化delegate的window.
self.window = [[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]]autorelease];
(2) 指定delegate所在window的rootViewController,即SwitchViewController,需要新建并初始化.
self.viewController = [[[SwitchViewControlleralloc]init]autorelease];
[self.viewControllerinitView];
self.window.rootViewController =self.viewController;
如下图:
二、自已创建MainWindow.xib并使用
新建一个window类型的xib命名为MainWindow.xib。如下图:
,新建好后,从Library中拖一个Object到界面上,指定其所属类为MVTestAppDelegate,
然后拖一个View Controller到界面上,并且指定所属类为SwitchViewController。
指定MainWindow.xib的File's Owner的所属类为UIApplication,并将其delegate与MVTestAppDelegate相连接:
接下来选中Test App Delegate,即MVTestAppDelegate,将viewController与界面上的Switch View Controller相连,window与window相连,
至此连完后,有个很重要的地方需要设置一下,那就是Info.plist,因为MainWindow.xib是自已创建的,所以需要指定NSMainNibFile为MainWindow。
然后运行一下,发现不行,会报错“Applications are expected to have a root view controller at the end of application launch”,那是因为没有在delegate启动时将rootViewController的view添加到delegate 的window中。虽然rootViewController(即MainWindow.xib中的Switch View Controller)已经在MainWindow.xib中指定并初始化了,但是并没有明确将该ViewController的view添加进来。另外还需要注意的一点是delegate的window已经在MainWindow.xib中初始化了。所以也不需要再通过
self.window = [[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]]autorelease];
来初始化了,此条不再需要,否则会发现rootViewController 的view被该新建的白色window挡住了,点back键可以看到退出动画时rootViewController 的view瞬间闪现。
即:
(1) 去掉delegate的window初始化过程:
//self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
(2) 添加rootViewController的view到delegate的window:
// 应用的rootViewController虽然已经在MainWindow.xib中定义并初始化了,但是还需要将之加到delegate的window上
[self.viewControllerinitView];
[self.windowaddSubview:self.viewController.view];
如下图:
并且在工程-》summary中mian interface改成mainwindow这不很重要不然前功尽弃
附:最终运行效果,即刚启动显示FirstViewController的view,点击Show Second,切换到SecondViewController的view,点上面的Show First 则切换回来,如下图:
总结:
不使用MainWindow.xib时,需要通过代码实现delegate的window的初始化,同时还需要初始化一个ViewController并且指定为 delegate的window的rootViewController.
使用MainWindow.xib时,Xcode4及以后的版本需要自已创建,并且添加delegate和rootViewController,同时注意File's Owner(所属类UIApplication)的delegate与添加的delegate连接,以及指定添加的Delegate的window和viewController与界面上window和添加的具体viewController连接。同时还需要在info.plist中指定NSMainNibFile键值。最后在delegate的启动完成接口中将MainWindow.xib中的rootViewController的view添加到delegate的window,并且去掉delegate的window的默认初始化过程.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(补充):
(1)没有MainWindow.xib时,需要指定应用Delegate的self.window和self.window.rootViewController,window和rootViewController都需要自已来定义、分配空间、初始化,在没有使用ARC的情况下,还需要控制内存回收。
(2)有MainWindow.xib时,并且在info.plist中指定了NSMainNibFile键值为MainWindow,则默认delegate的window即为MainWindow.xib中的window已经被定义和初始化了,内存回收什么的都不用我们管,并且在MainWindow.xib中若指定有UIViewController,则这个UIViewController也是定义并初始化了同window一样不用我们来管理内存回收。即,我们直接用里面的window和UIViewController即可。唯一需要注意的就是:MainWindow.xib中的UIViewController虽然不再需要我们来定义并初始化,但是这个UIViewController还没有被添加到self.window,所以我们唯一需要做的就是将这个UIViewController的view添加到self.window,或者使用这个UIViewController来初始化一个UINavigationController,然后将这个UINavigationController的view添加到self.window即可。
注:MainWindow.xib中不一定非得添加和指定View Controller,若在MainWindow.xib中添加了使用时也不一定就非得作为rootViewController,来添加到self.window,换句话说就是也可以做为rootViewController的子view controller被添加,只是在MainWindow.xib中添加了它的话使用它时不需要定义和初始化罢了(前提是需要在应用delegate头文件里面添加该viewController的IBOutlet,并且在MainWindow.xib界面中选中该delegate,然后将这个delegate中刚添加的IBOutlet与界面上的viewController相关联即可)。若没有在MainWindow.xib中添加那在存在xViewController.h、xViewController.m、xViewController.xib的情况下,使用前使用alloc init autorelease(若使用的地方没有retain则不要使用autorelease)进行一下定义和初始化并适当控制内存回收即可.
(注:后来发现self.window.rootViewController = self.myNavController ;和[self.window addSubview:self.myNavController.view];二者等价.)
通过这些可以猜想也可以在MainWindow.xib中添加多个view controller,然后在应用delegate里面添加对应view controller 的 IBOutlet,并且在MainWindow.xib中选中这个应用delegate将其添加的IBOutlet与界面上的view controller对应关联,然后就可以在应用delegate里面直接用这些在MainWindow.xib中添加的view controller了,不再需要关心空间分配、初始化及内存回收管理等工作。
另外,新建UIViewController的时候,可以选中With XIB for user interface,那么这个UIViewController的界面可以直接在对应的xib文件中通过Interface Builder进行设计,也可以直接在对应*.m中的viewDidLoad中进行代码设计。具体在xib中设计,又想在代码中关联并使用那就是添加IBOutlet和IBAction进行拖拽连接的问题了,前面“iPhone开发学习笔记001——Xib界面上的控件与代码的相互关联方法”中有介绍.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
文章其中部分内容来源于网上看到的一位大牛“漫步的空间”的博客,主要是SwitchViewController的定义和实现!作个记录,以免时间长了忘记了!本人涉足iPhone开发不久,好多地方可能描述有错误,请大牛遇到帮忙指教,小弟非常感谢!