第11课: iPad Considerations

split view  UISplitViewController

pop over  UIPopoverController

1. Storyboard 框架

The Storyboard Defines the Structure

Creating a SplitView Project

Master-Detail Application 模板

for pad,use ARC,use Storyboard

模板包含

app delegate

BIDMasterViewController

BIDDetailViewController

A split view controller that contains all the elements;

splitViewController作为stroyboard初始视图控制器

A navigation controller to handle what‘s happening on the left side of the split;

左侧有个navigation controller

A master view controller (displaying a master list of items) inside the navigation controller;

左侧的navigation controller的topViewController是master view controller

A detail view controller on the right.

右侧也是一个navigation view controller,其中有个detail view controller

UISplitViewController

@implementation BIDAppDelegate

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

//下面代码只是用来设置stroyboard中,无法设置的sense与sense之间对象的关联

// Override point for customization after application launch.

UISplitViewController *splitViewController =  (UISplitViewController *)self.window.rootViewController;

//有两个navigationcontroller,left and right,此时获取的是right,detailViewController

UINavigationController *navigationController = [splitViewController.viewControllers lastObject];

//设置splitViewController的委托,用来在detail view controller中响应左侧视图显示隐藏

//设置委托,用于响应横竖屏幕下,popOverController的显示和消失

splitViewController.delegate =  (id)navigationController.topViewController;  //navigationController的顶层视图控制器

return YES;

}

@end

为什么不直接在stroyboard中设置此委托?

a complex storyboard is not normally loaded all at once。

Since Interface Builder has no way of knowing which scenes will coexist, it actually forbids you from

making any outlet or target/action connections from an object in one scene to an object in another

scene. In fact, the only connections it allows you to make from one scene to another are segues.

storyborad中的sence不是一起加载的,而是按需加载。

正因为如此,IB不知道哪些sence会同时存在,

所以它禁止关联任何outlet或者target/action,在不同sence的对象之间。

实际上,唯一能在不同sence之间关联的,只有segue

所以我们必须在代码中,手动连接不同sence之间的对象。

The Master View Controller

@class BIDDetailViewController;

@interface BIDMasterViewController : UITableViewController

@property (strong, nonatomic) BIDDetailViewController *detailViewController;

@end

- (void)awakeFromNib

{

self.clearsSelectionOnViewWillAppear = NO;   //再次显示,保存单元的选中

self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);

[super awakeFromNib];

}

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

self.navigationItem.leftBarButtonItem = self.editButtonItem;  //前面讲过,每个viewController都有此按钮,用来翻转编辑状态

self.navigationItem.rightBarButtonItem =

[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd

target:self

action:@selector(insertNewObject:)];

//不就是前面设置的委托?

self.detailViewController = (BIDDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];

}

The Detail View Controller

@interface BIDDetailViewController ()

@property (strong, nonatomic) UIPopoverController  *masterPopoverController;

- (void)configureView;

@end

//Creating a class extension lets you define some methods and properties that are going to be used

//within your class but that you don’t want to expose to other classes in a header file.

//使用名称为空的扩展,定义私有的属性和方法

//如果只是定义实例变量,则可直接在{ }中

@implementation BIDDetailViewController

#pragma mark - Managing the detail item

- (void)setDetailItem:(id)newDetailItem

{

if (_detailItem != newDetailItem)//strong对象,所以能直接比较对象地址,来区分是否为同一个

{

_detailItem = newDetailItem;

[self configureView];

}

if (self.masterPopoverController != nil)

{

[self.masterPopoverController dismissPopover  Animated: YES];//竖向下,masterPopoverController非空,选择不同的object后,让popOver立即消失

}

}

- (void)configureView

{

if (self.detailItem)

{

self.detailDescriptionLabel.text = [self.detailItem description];

}

}

- (void)viewDidLoad

{

[super viewDidLoad];

[self configureView];

}

#pragma mark - Split view 委托方法(ios8中已经干掉此委托方法)

It‘s called when the split view controller is no longer going to show the left side of the split view as a permanent fixture.

当左侧不再固定显示的时候,调用此方法。即ipad从横屏转为竖屏时。

- (void)splitViewController:(UISplitViewController *)splitController

willHideViewController:(UIViewController *)viewController //left view controller

withBarButtonItem:(UIBarButtonItem *)barButtonItem

forPopoverController:(UIPopoverController *)popoverController

{

barButtonItem.title = NSLocalizedString(@"Master", @"Master");

[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];

self.masterPopoverController = popoverController;

}

连贯起来是,splitViewController将隐藏左侧masterViewController

但是通过barButtonItem,可以激活popoverController,来显示masterViewController

//the user switches back to landscape orientation

//从竖向,切换回横屏,popover机制消失,将会固定显示masterViewController

- (void)splitViewController:(UISplitViewController *)splitController

willShowViewController:(UIViewController *)viewController //left view controller

invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem //使得其无效

{

[self.navigationItem setLeftBarButtonItem:nil animated:YES];

self.masterPopoverController = nil;

}

@end

UIWebView

NSURL *url = [NSURL URLWithString: self.detailItem];

NSURLRequest *request = [NSURLRequest requestWithURL: url];

[self.webView loadRequest: request];

2. 自定义popover

Creating Your Own Popover

BIDLanguageListController: UITableViewController

@interface BIDLanguageListController : UITableViewController

@property (weak, nonatomic) BIDDetailViewController *detailViewController;

@property (strong, nonatomic) NSArray *languageNames;

@property (strong, nonatomic) NSArray *languageCodes;

@end

?

- (void)viewDidLoad

{

[super viewDidLoad];

self.languageNames = @[@"English", @"French", @"German", @"Spanish"];

self.languageCodes = @[@"en", @"fr", @"de", @"es"];

self.clearsSelectionOnViewWillAppear = NO; //view不显示的时候,选中不清空

//在popover中显示的大小

self.contentSizeForViewInPopover = CGSizeMake(320.0,  [self.languageCodes count] * 44.0);

[self.tableView registerClass:[UITableViewCell class]

forCellReuseIdentifier:@"Cell"];

}

#import <UIKit/UIKit.h>

@interface BIDDetailViewController : UIViewController <UISplitViewControllerDelegate>

@property (strong, nonatomic) id detailItem;

@property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;

@property (weak, nonatomic) IBOutlet UIWebView *webView;

@property (strong, nonatomic) UIBarButtonItem *languageButton;

@property (strong, nonatomic) UIPopoverController *languagePopoverController;

@property (copy, nonatomic) NSString *languageString;

- (IBAction)toggleLanguagePopover;

@end

- (void)viewDidLoad

{

[super viewDidLoad];

self.languageButton = [[UIBarButtonItem alloc] initWithTitle:@"Choose Language"

style:UIBarButtonItemStyleBordered

target:self

action:@selector(toggleLanguagePopover)];

self.navigationItem.rightBarButtonItem = self.languageButton;

[self configureView];

}

- (IBAction)toggleLanguagePopover

{

if (self.languagePopoverController == nil)

{

BIDLanguageListController *languageListController = [[BIDLanguageListController alloc] init];

languageListController.detailViewController = self;

UIPopoverController *poc = [[UIPopoverController alloc]

initWithContentViewController: languageListController];

[poc presentPopoverFromBarButtonItem: self.languageButton

permittedArrowDirections: UIPopoverArrowDirectionAny

animated:YES];

self.languagePopoverController = poc;

}

else

{

if (self.languagePopoverController != nil)

{

[self.languagePopoverController dismissPopoverAnimated:YES];

self.languagePopoverController = nil;

}

}

}

总结:

1. MasterDetail模版,提供了一个框架

支持splitView

横屏下,master固定在左侧,通过tableview显示数据

竖屏下,master被隐藏,不过可以通过popover显示

右侧detail显示master中选中对象的具体细节

注意1:

此模版中,从splitViewController到navigationController,到masterViewController,再到detailViewController

相互之间,都可以取到对方的值

app.window.rootViewController ==  splitViewController

splitViewController.viewControllers == @[masterNavigation, detailNavigation];

masterNavigation.topViewController  == masterViewController

detailNavigation.topViewController == detailViewController

masterViewController和detailViewController,又分别知道其navigator

masterViewController和detailViewController, 还知道其splitViewController

Controller之间的关系都是相互的,只有各strong和weak的区别

比如在masterController中,想获取到detailController,可这么干:

detailViewController =  [ [ [self.splitViewController viewControllers] lastObject] topViewController];

注意2:私有成员的定义

数据成员,以下两种方式都可以,因为有一对{}

//@interface HYDMasterViewController () {

//    NSMutableArray *_objects; //私有数据成员

//}

//@end

@implementation HYDMasterViewController

{

NSMutableArray *_objects; //私有数据成员

}

但是属性和方法,不能定义在{}内,所以对于属性和方法,定义私有的话,只能采用空扩展的方法

@interface HYDDetailViewController ()

@property (strong, nonatomic) UIPopoverController *masterPopoverController;

- (void)configureView;

@end

2. 自定义popover也很简单:

1.自定义viewController,注意设置其在popOver中的大小

self.contentSizeForViewInPopover = CGSizeMake(320.0,  [self.languageCodes count] * 44.0);

2.通过某个控件弹出popOver

1)即初始化viewController

2)初始化popOver,通过方法initWithContentViewController

3)设置popOver显示效果presentPopoverFromBarButtonItem

BIDLanguageListController *languageListController = [[BIDLanguageListController alloc] init];

UIPopoverController *poc = [[UIPopoverController alloc]

initWithContentViewController: languageListController];

[poc presentPopoverFromBarButtonItem: self.languageButton

permittedArrowDirections: UIPopoverArrowDirectionAny

animated:YES];

时间: 2024-10-20 06:05:04

第11课: iPad Considerations的相关文章

安卓学习第11课——AutoCompleteTextView

...在百度上搜了这么一段.理解了ArrayAdapter的三个参数的用途 1. 这个小例子是要显示一个数组,我们就用ArrayAdapter,数组适配器,数据的数据类型<>是String类型的,数据的数据类型还可以是其他的包括对象类型的 2. ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(ArrayListDemo.this, android.R.layout.simple_list_item

第11课完成:“主主同步”的视频,浪费的时间太不值得

今天晚饭前,终于完成第11课的内容. 其实,如果不是"主主同步"这节视频耽误太多的时间,我是可以做到本周一就结束这1节的.而且,在我初看"L11-17-MySQL主主同步理论介绍及手把手脚本实操讲解w"这节视频时,也浏览到视频的后三分之一.知道oldboy讲到最后,虽然把"主主同步"搭建成功,但是,最后他如何实现的步骤,在这节视频里并没有录制上. 只恨自己的"完美主义"心态,明明知道这节视频里,最关键的部分没有录制上,还是坚持

node.js第11课(HTTPclient)

 一.http模块提供了两个函数http.request和http.get,功能是作为client向HTTPserver发起请求. Ext.Ajax.request({},function(response)) 1.http.request(options,callback)发起HTTP请求,接受两个參数,option是一个类似关联数组的对象, 表示请求的參数,callback是请求的回调函数,option经常使用的參数例如以下 host:请求站点的域名或IP地址 port:请求站点的端口,

(版本定制)第11课:Spark Streaming源码解读之Driver中的ReceiverTracker彻底研究和思考

本期内容: 1.ReceiverTracker的架构设计 2.消息循环系统 3.ReceiverTracker具体实现 上节课讲到了Receiver是如何不断的接收数据的,并且接收到的数据的元数据会汇报给ReceiverTracker,下面我们看看ReceiverTracker具体的功能及实现. ReceiverTracker主要的功能: 在Executor上启动Receivers. 停止Receivers . 更新Receiver接收数据的速度(也就是限流) 不断的等待Receivers的运行

3.11课&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;异常语句与for循环重复

异常语句try catch finally try//保护执行里面的代码段,若其中一句有错误,直接跳转到catch,不会管下面的内容 { Console.Write("请输入一个整数"); int a = int.Parse(Console.ReadLine()); Console.WriteLine("hello"); } catch //try中发现异常,直接执行,若try中无错,不执行 { Console.WriteLine("输入有误!"

第11课 OpenGL 飘动的旗帜

飘动的旗帜: 这一课从第六课的代码开始,创建一个飘动的旗帜.我相信在这课结束的时候,你可以掌握纹理映射和混合操作. 大家好!对那些想知道我在这里作了些什么的朋友,您可以先按文章的末尾所列出的链接,下载我那毫无意义的演示(Demo)看看先!我是bosco,我将尽我所能教您来实现一个以正弦波方式运动的图象.这一课基于NeHe的教程第六课,当然您至少也应该学会了一至六课的知识.您需要下载源码压缩包,并将压缩包内带的data目录连其下的位图一起释放至您的代码目录下.或者使用您自己的位图,当然它的尺寸必须

11课上笔记

上节课回顾: 1. 进程线程:I/O操作 , 计算操作 2. praamiko: 3. 协程: -微线程 和I/O结合 内容: 1. MySQL -- 程序 --socket客户端 2. 根据ip和端口进行连接 3. 发送指令(send) 7. 接受结果 --socket服务端 1. 运行起来 4. 获取命令(recv): xxxx 5. 解析命令: ...文件操作 ...文件内容操作 6. 返回结果 数据库管理系统(软件) --客户端 --服务端 SQL语句: 文件夹操作(数据库): 创建:

Python学习笔记 (第11课)

本节学习Python的格式化输出,文件操作以及json的简单用法 1.格式化输出 将非字符串类型转换成字符串,可以使用函数:str() 或者repr() ,(这两个函数的区别目前我还没搞懂,求解答) >>> str([1,2,3,4]) '[1, 2, 3, 4]' >>> repr([1,2,3,4]) '[1, 2, 3, 4]' >>> str(10) '10' >>> repr(10) '10' 可以使用str.ljust()

java 学习第11课,android 实现拨打电话的功能

1. 先布局界面,界面采用线性垂直方式来布局 在layout 界面文件中 activity_main.xml 中 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation=&