【代码清单3-1】 Password/Classes/RootVIEwController.m
#import "RootVIEwController.h"#import "MainVIEwController.h"#import "FlipsIDeVIEwController.h"@implementation RootVIEwController@synthesize infobutton;@synthesize flipsIDeNavigationbar;@synthesize mainVIEwController;@synthesize flipsIDeVIEwController;- (voID)vIEwDIDLoad {MainVIEwController*vIEwController = [[MainVIEwController alloc]initWithNibname:@"MainVIEw" bundle:nil];self.mainVIEwController= vIEwController;[vIEwControllerrelease];[self.vIEwinsertSubvIEw:mainVIEwController.vIEw belowSubvIEw:infobutton];}- (voID)loadFlipsIDeVIEwController {FlipsIDeVIEwController*vIEwController = [[FlipsIDeVIEwController alloc]initWithNibname:@"FlipsIDeVIEw" bundle:nil];self.flipsIDeVIEwController= vIEwController;[vIEwControllerrelease];//Set up the navigation barUINavigationbar*aNavigationbar = [[UINavigationbar alloc] initWithFrame:CGRectMake(0.0,0.0,320.0,44.0)];aNavigationbar.barStyle= UIbarStyleBlackOpaque;self.flipsIDeNavigationbar= aNavigationbar;[aNavigationbarrelease];UIbarbuttonItem*buttonItem = [[UIbarbuttonItem alloc]initWithbarbuttonSystemItem:UIbarbuttonSystemItemDonetarget:selfaction:@selector(toggleVIEw)];UINavigationItem*navigationItem = [[UINavigationItem alloc] initWithTitle:@"PasswordGenerator"];navigationItem.rightbarbuttonItem= buttonItem;[flipsIDeNavigationbarpushNavigationItem:navigationItem animated:NO];[navigationItemrelease];[buttonItemrelease];}- (IBAction)toggleVIEw {/* This method is called when the info or Donebutton is pressed. It flips the displayed vIEw from the main vIEwto the flipsIDe vIEw and vice-versa. */if(flipsIDeVIEwController == nil) {[selfloadFlipsIDeVIEwController];}UIVIEw*mainVIEw = mainVIEwController.vIEw;UIVIEw*flipsIDeVIEw = flipsIDeVIEwController.vIEw;[UIVIEwbeginAnimations:nil context:NulL];[UIVIEwsetAnimationDuration:1];[UIVIEwsetAnimationTransition:([mainVIEw supervIEw]?uiviewanimationtransitionFlipFromright : uiviewanimationtransitionFlipFromleft)forVIEw:self.vIEw cache:YES];if([mainVIEw supervIEw] != nil) {[flipsIDeVIEwControllervIEwWillAppear:YES];[mainVIEwControllervIEwWilldisappear:YES];[mainVIEwremoveFromSupervIEw];[infobutton removeFromSupervIEw];[self.vIEwaddSubvIEw:flipsIDeVIEw];[self.vIEwinsertSubvIEw:flipsIDeNavigationbar aboveSubvIEw:flipsIDeVIEw];[mainVIEwControllervIEwDIDdisappear:YES];[flipsIDeVIEwControllervIEwDIDAppear:YES];}else {[mainVIEwControllervIEwWillAppear:YES];[flipsIDeVIEwControllervIEwWilldisappear:YES];[flipsIDeVIEwremoveFromSupervIEw];[flipsIDeNavigationbarremoveFromSupervIEw];[self.vIEwaddSubvIEw:mainVIEw];[self.vIEwinsertSubvIEw:infobutton aboveSubvIEw:mainVIEwController.vIEw];[flipsIDeVIEwControllervIEwDIDdisappear:YES];[mainVIEwControllervIEwDIDAppear:YES];}[UIVIEwcommitAnimations];}-(BOol)shouldautorotatetoInterfaceOrIEntation:(UIInterfaceOrIEntation)interfaceOrIEntation{//Return YES for supported orIEntationsreturn(interfaceOrIEntation == UIInterfaceOrIEntationPortrait);}- (voID)dIDReceiveMemoryWarning {[superdIDReceiveMemoryWarning]; // Releases the vIEw if it doesn't have a supervIEw//Release anything that's not essential,such as cached data}- (voID)dealloc {[infobuttonrelease];[flipsIDeNavigationbarrelease];[mainVIEwControllerrelease];[flipsIDeVIEwControllerrelease];[superdealloc];}@end
m 文件中方法很多,值得我们关注有3 个:vIEwDIDLoad 、loadFlipsIDeVIEwController 和toggleVIEw ,下分别介绍这个3 个方法。
vIEwDIDLoad 是视图加载完成还没有显示时候回调的方法,在本应用中该方法是创建一个主视图控制器,下面语句就是从一个给定nib 文件名字创建一个控制器的通用方法:
MainVIEwController *vIEwController =[[MainVIEwController alloc] initWithNibname:@"MainVIEw" bundle:nil];
主视图控制器创建完成需要把指针赋值给本类的mainVIEwController 属性,因为该属性设置retain ,这样可以防止内存泄漏,接着再释放刚才创建的vIEwController 对象。
self.mainVIEwController= vIEwController;
[vIEwControllerrelease];
在vIEwDIDLoad 该方法最后,通过下面的语句实现,将创建的主视图控制器中的视图放入到当前视图中作为子视图,并且位于 按钮下面,在iOS 中视图可以有子视图,子视图摆放是有顺序的,前后顺序的不同会引起遮挡和影响事件响应。
[self.vIEw insertSubvIEw:mainVIEwController.vIEwbelowSubvIEw:infobutton];
与– insertSubvIEw:aboveSubvIEw: 类似的方法还有:
· –addSubvIEw: ,直接在前面增加子视图;
· –insertSubvIEw:atIndex: ,按照索引插入子视图;
· –exchangeSubvIEwAtIndex:withSubvIEwAtIndex: ,交换两个子视图的顺序,常用于视图切换。
loadFlipsIDeVIEwController 方法主要作用就是创建背后视图和上面的导航栏,创建背后视图控制器方法与主视图控制器方法一样,这里不再多说了。在iOS 中导航栏比较麻烦的控件,它涉及到导航栏(Navigation bar )、导航项目(Navigation Item )和导航按钮(bar button Item ),在导航栏中包含导航项目,导航项目包含导航按钮,导航项目可以有标题,导航按钮可以有左右两个按钮,它们的关系如图3-35 所示。
图3-35 导航栏、导航项目和导航按钮的关系
因此我们需要创建这3 个对象,首先创建导航栏使用下面的语句:
UINavigationbar *aNavigationbar = [[UINavigationBaralloc] initWithFrame:CGRectMake(0.0,44.0)];
使用该方法可以通过指定一个矩形轮廓来创建一个导航栏,创建完成导航栏后还要指定它的样式:
aNavigationbar.barStyle= UIbarStyleBlackOpaque;
创建完成导航栏接着创建导航按钮,然后再创建导航项目,再把导航按钮放到导航项目中。下面语句是创建一个导航按钮:
UIbarbuttonItem *buttonItem = [[UIbarbuttonItemalloc]
initWithbarbuttonSystemItem:UIbarbuttonSystemItemDone
target:selfaction:@selector(toggleVIEw)];
在该语句中指定了按钮的样式,同时指定了按钮点击事件触发的时候调用的方法toggleVIEw 。导航项目创建是通过下面语句实现的:
UINavigationItem *navigationItem =[[UINavigationItem alloc] initWithTitle:@"Password Generator"];
在该语句中通过指定标题来构造一个导航项目,然后再通过下面的语句把刚才创建的导航按钮放在到导航项目中,作为它的右按钮。
navigationItem.rightbarbuttonItem = buttonItem;
最后还要把导航项目放入到导航栏中,这个目标是通过下面语句实现的,并且要求动画显示:
[flipsIDeNavigationbar pushNavigationItem:navigationItemanimated:NO];
导航栏维护一个堆栈,通过发出pushNavigationItem:animated: 消息把一个导航项目压栈,发出popNavigationItemAnimated: 消息把一个导航项目出栈,当前视图显示的是栈顶的导航项目,所以,压栈可以进入下一级导航项目,而出栈可以返回以上一级导航项目。
toggleVIEw 方法是点击主视图的 按钮和背后视图的Done 按钮时候触发的方法,在该方法中实现了两个视图的切换。在该方法中主要涉及到两个知识点,一个是UIVIEw 切换问题,另一个是UIVIEw 动画问题。两个问题是相伴而生的,在UIVIEw 切换的时候往往伴随着动画发生。下面我们先看看UIVIEw 切换问题。
在视图切换有很多种方式,可以采用模态视图控制器切换、导航控制器切换和普通 视图控制器切换。在本应用中采用的是普通视图控制器却换,它是定义一个根控制器,通过根控制器来控制其它视图交替切换。RootVIEwController 就是视图控制器,其中有自己的VIEw 对象(根视图),当主视图加载时候,将主视图作为根视图的子视图放入,当主视图向背后面翻转的时候,把主视图从根视图中移除掉,把背后视图作为根视图的子视图放入。当背后面向主视图翻转的时候,把背后视图从根视图中移除掉,把主视图作为根视图的子视图放入,这样反反复复。
采用模态视图控制器可以参考苹果官方文档http://developer.apple.com/library/ios/#featuredarticles/VIEwControllerPGforiPhoneOS/ModalVIEwControllers/ModalVIEwControllers.HTML 。
下面我们看看toggleVIEw 方法的代码,该方法首先执行下面的语句,实现初始化背后视图控制器目的,这里有一个判断如果flipsIDeVIEwController 为nil 时候才去发出loadFlipsIDeVIEwController 消息,可以防止多重加载。
if(flipsIDeVIEwController == nil) {
[selfloadFlipsIDeVIEwController];
}
接下来通过下面语句从视图控制器其中获得主视图和背后视图,由于在vIEwDIDLoad 方法中创建了主视图控制器,在loadFlipsIDeVIEwController 方法中创建了背后视图控制器,因此在这里获得的视图对象不会是nil 的。
UIVIEw*mainVIEw = mainVIEwController.vIEw;
UIVIEw*flipsIDeVIEw = flipsIDeVIEwController.vIEw;
在iOS 中动画有多种形式,这里的视图翻转是属于UIVIEw 级别动画,UIVIEw 级别动画必须从[UIVIEw beginAnimations:nilcontext:NulL] 开始到[UIVIEwcommitAnimations] 结束。在本应用中与UIVIEw 级别动画有关代码如下:
[UIVIEwbeginAnimations:nil context:NulL];
[UIVIEwsetAnimationDuration:1];
[UIVIEwsetAnimationTransition:([mainVIEw supervIEw]
?uiviewanimationtransitionFlipFromright
: uiviewanimationtransitionFlipFromleft)forVIEw:self.vIEw cache:YES];
… …
[UIVIEwcommitAnimations];
setAnimationDuration: 语句设置动画持续时间,setAnimationTransition:forVIEw: cache: 方法中第一个参数定义动画转变类型,第二个参数是当前视图对象,第三个参数是是否使用缓冲区。动画转变类型是指动画样式,其取值是uiviewanimationtransition 枚举类型,uiviewanimationtransition 的成员有:
· uiviewanimationtransitionNone ,不指定过渡类型;
· uiviewanimationtransitionFlipFromleft ,指定从左侧翻转;
· uiviewanimationtransitionFlipFromright ,指定从右侧翻转;
· uiviewanimationtransitionCurlUp ,指定向上卷起;
· uiviewanimationtransitionCurlDown ,指定向下卷起。
虽然,在本应用中没有使用,但是UIVIEw 级别动画中还有一个重要方法setAnimationCurve: ,该方法可以设置动画曲线,动画曲线是决定动画进入和退出屏幕的方式。其它取值是UIVIEwAnimationCurve 枚举类型,UIVIEwAnimationCurve 的成员有:
· UIVIEwAnimationCurveEaseInOut ,淡入淡出,开始时候慢,慢变快,中间最快,然后变慢;
· UIVIEwAnimationCurveEaseIn ,淡入,开始时候慢然后越来越快;
· UIVIEwAnimationCurveEaSEOut ,淡出,开始快然后越来越慢;
· UIVIEwAnimationCurvelinear ,线性匀速,开始和结束是一个速度。
判断语句if ([mainVIEw supervIEw] != nil) {} 可以判断当前的视图是否为主视图,因为只有当前视图是主视图情况下主视图才有父视图,否则就是当前视图就是背后视图。如果当前视图是主视图时候代码如下:
[flipsIDeVIEwControllervIEwWillAppear:YES];
[mainVIEwControllervIEwWilldisappear:YES];
[mainVIEwremoveFromSupervIEw];
[infobutton removeFromSupervIEw];
[self.vIEwaddSubvIEw:flipsIDeVIEw];
[self.vIEwinsertSubvIEw:flipsIDeNavigationbar aboveSubvIEw:flipsIDeVIEw];
[mainVIEwControllervIEwDIDdisappear:YES];
[flipsIDeVIEwControllervIEwDIDAppear:YES];
上面的这段代码就是要实现从主视图向背后面翻转,因此,需要在根视图中移除主视图[mainVIEw removeFromSupervIEw] ,同时还移除了infobutton 对象[infobutton removeFromSupervIEw] ,它们两个都是在主视图上显示的。 [self.vIEwaddSubvIEw:flipsIDeVIEw] 方法把背后视图添加到当前视图。在通过 [self.vIEwinsertSubvIEw:flipsIDeNavigationbar aboveSubvIEw:flipsIDeVIEw] 语句把导航栏添加到背后视图上面,使得导航栏与背后视图同是当前视图的子视图,只不过是导航栏在前面。
此外,代码中还用到了控制器中视图出现和消失的几个事件方法:
· vIEwWillAppear: ,通知视图控制器,它的视图将要可见;
· vIEwWilldisappear: ,通知视图控制器,它的视图将要消失;
· vIEwDIDdisappear: ,通知视图控制器,它的视图已经消失;
· vIEwDIDAppear: ,通知视图控制器,它的视图已经可见。
事实上,这几个方法经常在视图控制器中被重写,用于处理视图的不同生命周期中会触发的事件,它们与vIEwDIDLoad 和vIEwDIDUnload 事件类似,它们调用会更加频繁触发。其中vIEwDIDLoad 和 vIEwWillAppear: 很类似,vIEwDIDLoad 是视图被创建时候触发,接着视图变成可见的时候会触发 vIEwWillAppear: 事件,当视图变换到别的视图,视图从可见变成不可见,再次回来时候,视图从不可见变成可见vIEwDIDLoad 方法就不会触发 ,而 vIEwWillAppear: 事件会触发。 @H_869_502@ 总结
以上是内存溢出为你收集整理的《iPhone与iPad开发实战—iOS经典应用剖析》连载五全部内容,希望文章能够帮你解决《iPhone与iPad开发实战—iOS经典应用剖析》连载五所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)