
这节课的主要内容包括iPad、Split VIEws、Popovers及做一个universal的应用并在两种设备上运行。
UIToolbar通常在屏幕的顶部或底部,长得像钢筋一样。一个工具栏,是一个UIbarbuttonItems的集合。UIbarbuttonItems不是按钮,有点像是简化过的按钮。UINavigationController有一个在底部的工具栏,可以通过在xcode里inspect Navigation Controller中的Shows Toolbar小开关打开,但工具栏上的按钮和Navigation Controller本身没有任何关系,它只和当时显示的VIEwController有关。
UIbarbuttonItems是使UIToolbar真正工作的东西,他们有target action,就像一个按钮。有两个特殊的UIbarbuttonItems,Fixed和Flexible space,这些都是用来安排你UIToolbar按钮的显示方式。创建一个UIbarbuttonItems的方式是alloc/init,它可以采用文字或图像,或者可以用另一种叫做initWithbarbuttonSystemItem的初始化方法,然后你给它在枚举类型中指定一个。
要创建一个工具栏非常简单,只需将其拖动到你的VIEwController,通常会连到一个outlet,然后只需从xcode中拖个UIbarbuttons到它里面,或者在代码中设置个数组,工具栏对象有个物品数组。
UISplitVIEwController创建一个UISplitVIEwController的方法是在xcode里将它托出来,只能拖动Split VIEw到一个ipad类型的storyboard。Split VIEw通常只是一个基本元素,它填满整个屏幕,不可能把Split VIEw放到其他什么的内部,一般情况下是提供给整个app的。Split VIEw有两个VIEwControllers,一个左侧一个右侧,左侧叫Master,右侧叫Detail。SplitVIEwController有一个property叫做VIEwControllers,它是一个数组,这个数组有两个元素,左侧和右侧,左侧是元素0,右侧是元素1,可以在代码中设置你的两个VIEwController(通常得同时设置),可以在xcode中设置这两个东西,可以control拖动到左侧来设置左侧或拖动到右侧来设置右侧,然后它要改变就用segue。
@property (nonatomic,copy) NSArray *vIEwControllers;
此API不希望你传递含有这两个VIEwController的可变数组,然后期待如果你改变了一个,它会以某种方式更新Split VIEw。所以这里说的是我要复制你给我的东西,而且我要使用它。所以如果你要改变它,你得再给我一次。就是不想让你传递可变数组,以防止你改变了它导致发生意外。
Split VIEw不能没有delegate,如果没有设置delegate,那么当Split VIEw进入Portrait模式的时候左侧就会消失,你应该在角落里放一个小按钮,使用户可以点击它来让左侧出现在popover里。这是Split VIEw的工作原理。如果不实现delegate就没办法放上那个按钮,就无法在portrait模式下调出左侧。通常情况下,你要在VIEwController的vIEwDIDLoad或awakeFromNib方法里设置此delegate。所以Split VIEw的delegate最主要的任务就是处理旋转,delegate是管理左侧的。
- (BOol)splitVIEwController:(UISplitVIEwController *)sender shouldHIDeVIEwController:(UIVIEwController *)master inorIEntation:(UIInterfaceOrIEntation)orIEntation{ return YES; // always hIDe it}
这个delegate方法是被发送到你的delegate询问在特定方向下你想要左侧做什么,因此它把自己传递给你,还有左侧,它会问在这个方向你想要我对左侧做什么。要隐藏就返回YES,要保留在屏幕上就返回NO。
return UIInterfaceOrIEntationIsPortrait(orIEntation);}这是如果不实现delegate其余的方法会出现的问题,因为portrait会隐藏左侧,但你没有放那个小按钮,系统不会帮你做这一步。它会给你按钮,但你得把它放到屏幕上。因此,其余的delegate方法就是要把按钮放上去。其中有两个非常重要,一个用来把按钮放上去,一个用来把按钮拿掉。例如旋转回Landscape:
- (voID)splitVIEwController:(UISplitVIEwController *)sender willHIDeVIEwController:(UIVIEwController *)master withbarbuttonItem:(UIbarbuttonItem *)barbuttonItem forPopoverController:(UIPopoverController *)popover{ barbuttonItem.Title = @“Master”; use a better word than “Master”! setSplitVIEwbarbuttonItem: must put the bar button somewhere on screen probably in a UIToolbar or a UINavigationbar [detailVIEwController setSplitVIEwbarbuttonItem:barbuttonItem];}
这是用来隐藏左侧的,它给你一个barbutton,就是第三个参数,它说把这个barbutton放到屏幕上,因为我将要隐藏左侧的VIEwController。当这个barbutton被按下,它会自动显示左侧,但是必须把barbutton放到某处。
当你想要旋转回Landscape,并把左侧放回到屏幕上,它会向你发送此消息:
voID)splitVIEwController:(UISplitVIEwController *)sender willShowVIEwController:(UIVIEwController *)master invalIDatingbarbuttonItem:(UIbarbuttonItem *)barbuttonItem{ removeSplitVIEwbarbuttonItem: must remove the bar button from its toolbar [detailVIEwController removeSplitVIEwbarbuttonItem:nil];}这就是把按钮从工具栏里移除,因为不想左侧显示时,还有这个按钮。
有很多办法可以用来实现SplitVIEw delegate,这取决于在两侧使用的是什么VIEwController。何时该设置delegate:一、你得决定谁是delegate,是左侧的Master还是右侧detail?此外你得去考虑可重用性,两者之一可能是通用的,所以不能在那上面实现SplitVIEw delegate,它是一个通用的可重复使用的vIEw。这有个例子,在Detail一侧总是把按钮放上去,那么按钮就总是在Detail一侧。
voID)setSplitVIEwbarbuttonItem:(UIbarbuttonItem *)barbuttonItem{ UIToolbar *toolbar = [self toolbar]; might be outlet or calculated NSMutableArray *toolbaritems = [toolbar.items mutablecopy]; if (_splitVIEwbarbuttonItem) [toolbaritems removeObject:_splitVIEwbarbuttonItem]; put the bar button on the left of our existing toolbar if (barbuttonItem) [toolbaritems insertObject:barbuttonItem atIndex:0]; toolbar.items = toolbaritems; _splitVIEwbarbuttonItem = barbuttonItem;}这个方法会把barbuttonItem插入到工具栏的最左侧,不管工具栏里的其他东西它都会被插在左侧。
通常,点击Master里的东西,Detail显示你点击的东西的详细信息。那么当Master改变时,Detail是怎么更新的?有两个选择,一是简单的target action,在左侧的Master VIEw你已经有了一些按钮或什么,当被点击它会发送target action消息给你的Master Controller。当它想更新Detail,它只要发一个消息到Detail。它是如何从Master得到Detail的?例如Master VIEw Controller里一个target action消息叫doit:
- (IBAction)doit{ ID detailVIEwController = [[self.splitVIEwController vIEwControllers] lastObject]; [detailVIEwController setSomeProperty:...];}
二是也可以segue,在SplitVIEwController里只有一种segue能用,它被称为replace segue,这是因为它会替换Master或Detail。使用replace segue有个要警告的地方:当你替换Detail VIEw的时候,如果工具栏里有SplitVIEw barbutton,该工具栏也被替换,因为整个vIEw都会被替换,所以你得把SplitVIEw barbutton转移出来,得把它转移到新的delegate生成的popover上,通常在准备segue的时候去完成做这些。所以如果你要准备segue,你需要问detail关于它的barbutton,你设置barbutton,然后让segue发生。
Popover就是漂浮选单,它只是一个NSObject,它控制VIEwController,它的工作基本上就是通过contentVIEwController绘制它的VIEwController。通常Popover发生内容,是因为你control拖动它,并有一个segue。Popover segue做的是,你control拖动它到VIEwController,它会把VIEwController放到Popover里,不管是从按钮或什么拖动,那就是Popover的指向。如果你在代码中做Popover,或使用了storyboard,在storyboard的方法instantiateVIEwControllerWithIDentifIEr会给你一个storyboard外部的VIEwController。如果得到一个VIEwController,然后发消息给UIPopoverController,进行alloc/init就有了PopoverController,你向其发送这两个消息之一,使其出现在屏幕上。
- (voID)presentPopoverFromrect:(CGRect)aRect or inVIEw:(UIVIEw *)vIEw permittedArrowDirections:(UIPopoverArrowDirection)direction animated:(BOol)flag;voID)presentPopoverFrombarbuttonItem:(UIbarbuttonItem *)barbuttonItem permittedArrowDirections:(UIPopoverArrowDirection)direction animated:(BOol)flag;
得保持一个strong指针指向你的PopoverController,所有这些显示的东西都不会有strong指针指向你的PopoverController。
消除Popover,把它从屏幕上去掉,通常是用户触发的,有两种方式:一是如果点击了屏幕上除Popover以外的地方,它会关闭Popover;当你点击Popover里的东西,它是怎么消除的呢?答案是调用了dismisspopoverAnimated,但你不能从popover里的VIEwController调用dismisspopoverAnimated。不管把Popover放上来的是哪个对象,这个对象就应该负责消除Popover。
Popover有delegate,实际上它有两个方法,一是问你是否要消除,另一个是告诉你它何时被消除,但这只发生在有人通过点击Popover以外的地方来消除的情况。
设置Popover大小的方式:一最常用的方法是在xcode里设置,选中一个VIEwController并inspect它,通过Popover小开关打开并指定大小;二是通过UIVIEwController中的contentSizeforVIEwInPopover方法;第三种方式是UIPopoverController有个方法可以设置Popover的大小。
Universal Applications一个通用app就是单一一个应用程序,但可以运行在ipad或iphone上,可以共享VIEwController。调用这个宏UI_USER_INTERFACE_IdioM可以知道在ipad上运行,你问它是UIUserInterfaceIdiomPad还是UIUserInterfaceIdiomPhone,这会告诉你是否在ipad上运行:
BOol iPad = (UI_USER_INTERFACE_IdioM() == UIUserInterfaceIdiomPad);
但这不是最好的办法,询问我是否处在SplitVIEwController里会更好。
Demo修改上一节的demo,使其成为一个通用app,其中要创建一个ipad的storyboard。
修改spring&structs,如果视图控制器是UIVIEwController类,则需要一个UIVIEwController子类重载shouldautorotatetoInterfaceOrIEntation方法才能进行旋转。创建完UIVIEwController的子类后只要留下shouldautorotatetoInterfaceOrIEntation方法,并使它返回yes。
修改app设置使其成为一个通用app,把原来的MainStoryboard.storyboard改为:iPhone.storyboard,修改iPhone的storyboard:
新建iPad.storyboard,并设置iPad的storyboard。
在iPad.storyboard里拖一个SplitVIEwController进来,删除tableVIEwController,修改右侧控制器的类为HappinessVIEwController,再拖一个VIEw到HappinessVIEwController并把它的类修改为FaceVIEw,要设置outlet和action。在iPhone.storyboard中复制根视图控制器,到iPad.storyboard再粘贴,从导航控制器control拖动到根视图控制器,再把Psychologist VIEw Controller粘贴过来并用segue关联起来:
修改PsychologistVIEwController.m中的代码如下:
- (HappinessVIEwController *)splitVIEwHappinessVIEwController{ ID hvc = [self.splitVIEwController.vIEwControllers lastObject]; if (![hvc isKindOfClass:[HappinessVIEwController class]]) { hvc = nil; } return hvc;}- (voID)setAndShowDiagnosis:(int)diagnosis{ self.diagnosis = diagnosis; if ([self splitVIEwHappinessVIEwController]) { [self splitVIEwHappinessVIEwController].happiness = diagnosis; }else{ [self performSegueWithIDentifIEr:@"ShowDiagnosis" sender:self]; }}
把SplitVIEw delegate放进RotatableVIEwController,让RotatableVIEwController成为SplitVIEw的delegate。RotatableVIEwController的代码如下:
#import <UIKit/UIKit.h>@interface RotatableVIEwController : UIVIEwController<UISplitVIEwControllerDelegate>@end
#import "RotatableVIEwController.h"SplitVIEwbarbuttonItemPresenter.h@implementation RotatableVIEwController- (voID)awakeFromNib{ [super awakeFromNib]; self.splitVIEwController.delegate = self;}- (ID <SplitVIEwbarbuttonItemPresenter>)splitVIEwbarbuttonItemPresenter{ ID detailVC = [self.splitVIEwController.vIEwControllers lastObject]; if (![detailVC conformstoprotocol:@protocol(SplitVIEwbarbuttonItemPresenter)]) { detailVC = nil; } return detailVC;}- (BOol)splitVIEwController:(UISplitVIEwController *)svc shouldHIDeVIEwController:(UIVIEwController *)vc inorIEntation:(UIInterfaceOrIEntation)orIEntation{ return [self splitVIEwbarbuttonItemPresenter]? UIInterfaceOrIEntationIsPortrait(orIEntation) : NO;}- (voID)splitVIEwController:(UISplitVIEwController *)svc willHIDeVIEwController:(UIVIEwController *)aVIEwController withbarbuttonItem:(UIbarbuttonItem *)barbuttonItem forPopoverController:(UIPopoverController *)pc{ barbuttonItem.Title = self.Title; [self splitVIEwbarbuttonItemPresenter].splitVIEwbarbuttonItem = barbuttonItem;}- (voID)splitVIEwController:(UISplitVIEwController *)svc willShowVIEwController:(UIVIEwController *)aVIEwController invalIDatingbarbuttonItem:(UIbarbuttonItem *)barbuttonItem{ [self splitVIEwbarbuttonItemPresenter].splitVIEwbarbuttonItem = nil;}- (BOol)shouldautorotatetoInterfaceOrIEntation:(UIInterfaceOrIEntation)interfaceOrIEntation{ Return YES for supported orIEntations return YES;}@end
创建一个protocol,代码如下:
@protocol SplitVIEwbarbuttonItemPresenter <NSObject>@property (nonatomic,strong) UIbarbuttonItem *splitVIEwbarbuttonItem;HappinessVIEwController .h文件代码:
#import <UIKit/UIKit.h>@interface HappinessVIEwController : UIVIEwController<SplitVIEwbarbuttonItemPresenter>@property (nonatomic) int happiness; 0 is sad; 100 is very happyHappinessVIEwController.m实现协议:
HappinessVIEwController.h"FaceVIEw.h@interface HappinessVIEwController() <FaceVIEwDataSource>@property (nonatomic,weak) IBOutlet FaceVIEw *faceVIEw;@property (nonatomic,weak) IBOutlet UIToolbar *toolbar;@end@implementation HappinessVIEwController@synthesize happiness = _happiness;@synthesize faceVIEw = _faceVIEw;@synthesize splitVIEwbarbuttonItem = _splitVIEwbarbuttonItem;@synthesize toolbar = _toolbar;- (voID)setSplitVIEwbarbuttonItem:(UIbarbuttonItem *)splitVIEwbarbuttonItem{ if (_splitVIEwbarbuttonItem != splitVIEwbarbuttonItem) { NSMutableArray *toolbaritems = [self.toolbar.items mutablecopy]; if (_splitVIEwbarbuttonItem) { [toolbaritems removeObject:_splitVIEwbarbuttonItem]; } if (splitVIEwbarbuttonItem) { [toolbaritems insertObject: splitVIEwbarbuttonItem atIndex:0 ]; } self.toolbar.items = toolbaritems; _splitVIEwbarbuttonItem = splitVIEwbarbuttonItem; }}.......运行结果如下所示:
总结以上是内存溢出为你收集整理的iOS应用开发视频教程笔记iPad Apps全部内容,希望文章能够帮你解决iOS应用开发视频教程笔记iPad Apps所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)