有两个scene,分别为Scene A和Scene B。Scene A上有一个UIButton(Button A)和一个UILable(Lable A);Scene B上有一个UITextFiled(textFiled)。当单击Scene A上的Button A时,跳转到Scene B,在Scene B的textFiled上输入文字,单击键盘的“完成”按钮,返回到Scene A,并在Scene A的Lable A上显示刚才输入的内容。

  这是一个典型的场景之间的跳转和逆向传值问题,看似简单,却暗藏杀机。我们不仅要使用Storyboard框架,还要采用Delegate模式,最后达到题目要求。

Delegate

什么是Delegate?跟这道题目又有什么关系呢?

简单分析一下题目,主要包括Storyboard的应用,页面跳转,数据的交互,似乎跟Delegate没什么关系呢。在这里我决定先不刨根问底,留一个小悬念,在实际的解决问题的过程中去慢慢“悟”关于Delegate的一切,它是一种设计模式,并不是那么简单就能描述清楚的。

页面之间的数据传递

iOS提供了多种方法,来实现页面之间的数据传递:

  • 使用SharedApplication,定义一个类似全局的变量来传递

  • 使用文件,或者使用NSUserdefault来传递

  • 通过一个单例(SingleXX)的class来传递

  • 通过Delegate来传递

关于数据的存储方式共有五种:

  • User Defaults

  • Property List(对应)

  • Object archives

  • SQLite

  • Core Data

在本道题目当中,显然采用Delegate方式是最佳方案。

界面搭建

有了先前我们使用Storyboard的经验,我们先很快的对界面进行搭建。先抛开所有的segue不管,先把题目中描述的情况展现出来再说。

我们新建名为delegateSentValue的工程,在原有viewController的基础上再新建一个,同时新建名为viewController2的.h和.m文件,对它们进行关联。再向两个view中拖放组件,并且将它们关联到相应的文件。这个过程应该是很简单的,我们暂且不管需要响应事件的Button,只是将两个Lable和一个textFiled在两个.h文件中进行属性声明。完成后如下图:

搭建完成界面之后,我们先实现从Scene A到Scene B的跳转。通过“Ctrl+drag”操作,将Button与Scene B关联,设置为“modal”模式,然后我们选中这个Segue,将它的identifier命名为Segue_ID_AB。

我们可以先来运行下,这时我们可以实现通过点击按钮实现页面正向跳转的功能,点击输入框,我们可以接受键盘的输入。

Delegate应用

我们所剩的任务还有输入内容,单击键盘上的“完成(return)”按钮,返回Scene A,并将刚才输入的内容显示在Scene A中。

对于一个Delegate应用,需要5步来完成:

  • 委托者声明一个Delegate

  • 委托者调用Delegate内的方法

  • 关联委托者与被委托者

  • 被委托者遵循Delegate协议

  • 被委托者重写Delegate内的方法

  • 委托者声明一个Delegate

在ViewController2中,#import下,@interface前添加如下代码:

1
2
@protocol ViewController2Delegate -(void) viewController2:(ViewController2 * )sceneBVC didInputed:(NSString * )string;
@end

在@interface中声明:

1
@property (weak, nonatomic) id  delegate;

通过@protocol创建一个Delegate并声明。

这里需要注意的一点是,如果仅仅是按照上面的要求去添加代码,会出现“Expected a type.”的错误,原因是我们要使用ViewController2类型,而这个类型先前是没有定义过的,可是如果我们把@protocol,也就是上面三行代码移到@property下面去的时候呢,在声明中的ViewController2Delegate又出现了同样的问题。于是乎,我们需要修改一下代码的结构,我们首先创建Delegate,然后声明,最后再在@interface的后面定义Delegate内的方法,这样一来就没有问题了。最后完整的ViewController2.h的代码如下:

1
2
3
4
5
6
7
8
#import @protocol ViewController2Delegate;
@interface ViewController2 : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *showInformation2;
@property (weak, nonatomic) IBOutlet UITextField *inputInformation;
@property (weak, nonatomic) id  delegate;
@end
@protocol ViewController2Delegate -(void) viewController:(ViewController2 *) sceneBVC didInputed:(NSString *) string;
@end

委托者调用Delegate内的方法

解决了上面的问题后,这一步就比较简单了,添加代码即可:

1
2
3
4
5
6
7
8
9
10
11
-(BOOL)textFieldShouldReturn:(UITextField *) textField{
if (self.delegate) {
//将UITextField内容传递给Delegate内的方法
[self.delegate viewController:self didInputed:self.inputInformation.text];
//让当前呈现的Scene B页面消失
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
//让键盘消失
[textField resignFirstResponder];
return YES;
}

仅仅添加代码是远远不够的,我们还要关联,具体做法是在Storyboard中,选中ViewController2中的TextFiled控件,采用“Ctrl+drag”操作将其与ViewController2关联。

在Outlets中选中delegate。

关于让键盘消失这个问题,我会单独写篇文章说明,在这里先占个坑。

关联委托者与被委托者

明确这两者的关系在Delegate的应用中显得尤为重要,在ViewController.m中添加如下代码:

1
2
3
4
5
6
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:@"Segue_ID_AB"]) {
ViewController2 *sceneBVC = segue.destinationViewController;
sceneBVC.delegate = self;
}
}

在完成上面代码之后可能会收到来自编译器的报错,不过不用担心,等我们完成所有步骤,把代码完善了以后就没问题了。

这里最重要的就是prepareForSegue方法的使用,该方法的完整描述是:

1
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

segue:用以描述一个跳转的相关信息,比如是A controller 跳转至B controller页面,则我们可以通过它获取到Acontroller的一个实例对象,和B controller的一个实例对象。注意调用这个函数的时候,跳转行为还没有发生,所以我们可以在这个方法内部,获取到B controller的实例,然后传递一些参数过去。

sender:表示是谁触发了这次跳转。因为是从A--->B,所以这个sender可能是A controller里面的任何一个对象。我们可以用它来区分同一个页面上触发的不同的跳转行为。

比如:A页面上有2个按钮x和y,当点击x按钮时,就跳B页面;当点击y按钮时,就跳C页面。所以当点击x按钮时,触发了一个跳转,UIStoryboard的运行时就会去调用A controller里面的这个函数,其中sender就是x按钮。点击y按钮类似。这时候我们就可以判断如果sender是x按钮,则给B页面传递数据;如果按钮时y,则给C页面传递数据。或者是其他业务逻辑。

相关资料:storyboard之prepareForSegue

被委托者遵循Delegate协议

在ViewController.h中引入ViewController2.h,并让ViewController遵循委托者协议:

1
2
3
4
5
#import //引入
#import "ViewController2.h"
//让ViewController遵循委托者协议
@interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *showInformation;
@end

被委托者重写Delegate内的方法

在ViewController.m中,重写Delegate内的方法:

1
2
3
-(void)viewController:(ViewController2 *)sceneBVC didInputed:(NSString *)string{
self.showInformation.text = string;
}

测试与总结

先上图!

这样,我们就完整的解决了这个看似简单实际暗藏玄机的题目了。

Delegate实现了不同场景之间的数据交互。它属于事件驱动的范畴,只有当某一事件触发时,Delegate才被调用。从这到例题中我们使用到的Delegate还只是很少的一部分,想要熟练的使用并且有深入的理解还需要更多的探索。

iOS delegate的更多相关文章

  1. [iOS]delegate和protocol

    转自:http://haoxiang.org/2011/08/ios-delegate-and-protocol/ 今天上班和同事讨论工程怎么组织的时候涉及到这个话题.iOS开发上对delegate使 ...

  2. ios delegate你必须知道的事情

    在我们的class中设计delegate的时候,我们通常会有几个注意事项. 假设我的class叫做MyClass,那我们可能会有定义一个MyClassDelegate这个protocol当作我的del ...

  3. ios delegate, block, NSNotification用法

    ios中实现callback可以通过两种方法,委托和NSNotification 委托的话是一对一的关系,例如一个UIViewController里有一个tableView, 将该viewContro ...

  4. iOS delegate, 代理/委托与协议.

    之前知知道iOS协议怎么写, 以为真的跟特么java接口一样, 后来发现完全不是. 首先, 说说应用场景, 就是当你要用一个程序类, 或者说逻辑类, 去控制一个storyboard里面的label, ...

  5. ios delegate 代理模式 观察者模式 不同视图间的通信

    delegate,在ios中比比皆是,NSURLConnection(网络请求有),tableView, connectionView,等系统自带 的常见代理.甚至,自己写代码的时候,随意间敲打出了p ...

  6. iOS 之美:iOS Delegate 使用五步曲

    在iOS 开发中, 搞清楚Delegate 是需要花些时间的. Delegate 本来是软件架构设计的一种理念.对于像手机这样一个有限的设备,我们需要充分考虑到:内存要尽量省着用: 视图之间的关系要清 ...

  7. 转:ios delegate

    首先,大家应该都明白的是委托是协议的一种,顾名思义,就是委托他人帮自己去做什么事.也就是当自己做什么事情不方便的时候,就可以建立一个委托,这样就可以委托他人帮自己去实现什么方法. 其次,我简单的总结了 ...

  8. ios delegate 使用注意 assign,weak

    今天一个同事写代码,把一个delegate对象设定成了assign类型属性,没有用weak,就是delegate对象释放后,不会把delegate指针自动设定为nil,把对象的delegate设定成了 ...

  9. IOS - delegate为什么不使用retain

    循环引用所有的引用计数系统,都存在循环应用的问题.例如下面的引用关系: 对象a创建并引用了对象b.对象b创建并引用了对象c.对象c创建并引用了对象b. 这时候b和c的引用计数分别是2和1.当a不再使用 ...

随机推荐

  1. Mysql数据库 - 增删改

    一. Create 1. 单条插入, sql格式: insert into (列名) values(列值); INSERT INTO test.tch_teacher ( Sex, BId, NO, ...

  2. jquery Combo Select 下拉框可选可输入插件

    Combo Select 是一款友好的 jQuery 下拉框插件,在 PC 浏览器上它能模拟一个简单漂亮的下拉框,在 iPad 等移动设备上又能回退到原生样式.Combo Select 能够对选项进行 ...

  3. 快速排序中的partition函数的枢纽元选择,代码细节,以及其标准实现

    很多笔试面试都喜欢考察快排,叫你手写一个也不是啥事.我很早之前就学了这个,对快速排序的过程是很清楚的.但是最近自己尝试手写,发现之前对算法的细节把握不够精准,很多地方甚至只是大脑中的一个映像,而没有理 ...

  4. python httplib get和post获取数据

    httplib 下的 status http请求的状态  200 404 500... reason 返回答复 OK或者 FAULRE read()  读取内容 get方法: #!/usr/bin/e ...

  5. CGI, FastCGI, WSGI, uWSGI, uwsgi简述

    CGI 通用网关接口(Common Gateway Interface/CGI)是一种重要的互联网技术,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据.CGI描述了服务器和请求处理程 ...

  6. 子元素使用float 父元素撑开方法

    一个Div包含了多个子Div,并且子Div使用了浮动后,父Div确不能被撑开,如下图: 部分代码如下: 1 <style> 2   #div1{border:1px solid red;f ...

  7. 4 django系列之HTML通过form标签来同时提交表单内容与上传文件

    preface 我们知道提交表单有2种方式,一种直接通过submit页面刷新方法来提交,另一种通过ajax异步局部刷新的方法提交,上回我们说了通过ajax来提交文件到后台,现在说说通过submit来提 ...

  8. Web Service简要概念,学习记录!

    Web Service平台需要一套协议来实现分布式应用程序的创建.任何平台都有它的数据表示方法和类型系统.要实现互操作性,Web Service平台必须提供一套标准的类型系统,用于沟通不同平台.编程语 ...

  9. SecureCRT上传和下载文件

    SecureCRT上传和下载文件(下载默认目录) SecureCR 下的文件传输协议有ASCII .Xmodem .Ymodem .Zmodem ASCII:这是最快的传输协议,但只能传送文本文件. ...

  10. php中引用&的真正理解-变量引用、函数引用、对象引用

    php的引用(就是在变量或者函数.对象等前面加上&符号) //最重要就是 删除引用的变量 ,只是引用的变量访问不了,但是内容并没有销毁 在PHP 中引用的意思是:不同的名字访问同一个变量内容. ...