ios开发——实用技术篇Block/KVO/通知/代理
关于iOS开发中数据传递的方法有很多种,但是使用最多的就是这里的四种,而且我们要学会在适当的时候使用合适的方式,才能充分的提高app的性能
下面简单介绍一下这些方法的使用
Block
第一、综述
block是OC中另外一种对象和对象的通信方式,是一对一的关系,类似于delegate,而通知时一对多的关系
第二、定义block类型
int (^myBlock)(int)
第三、block的声明
mylock=^(int a)
{
int result =a*a;
return result;
}
第四、block的调用
block(20);
code sample如下所示:
int(^myBlock)(int); myBlock=^(int a){ NSLog(@"%d",a); return 0; }; myBlock(20);
第五、另外一种声明方法
typedef int(^MyBlock)(int);
MyBlock myblock=^(int a)
{
NSLog(@"%d",a);
return 30;
};
myblock(30);
第六、block作为参数传递
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//define block defination
NSLog(@"before");
MyBlock myblock=^(int a)
{
NSLog(@"%d",a);
return 30;
};
[self testBlock:myblock];
}
-(void)testBlock:(MyBlock)myblock
{
myblock(10);
}
第七、block和变量
局部变量:
在block中,会把局部变量当成常量变量
int num=10;
int num=30;
MyBlock myblock=^(int a)
{
num=20; //此处会报错
NSLog(@"%d",a);
return 30;
};
1 什么是Block:从C的声明符到Objective-C的Blocks语法 2 块代码以闭包得形式将各种内容进行传递,可以是代码,可以是数组无所不能。块代码十分方便将不同地方的代码集中统一,使其易读性增强。 3 4 来看这里怎么进行数组传递。 5 6 typedef void (^Arr_Block)(NSArray *array); 7 8 - (void)showArrayUsingBlock:(Arr_Block)block 9 { 10 NSDictionary *dict = @{@"array": @[@"Chelsea", @"MUFC", @"Real Madrid"]}; 11 NSArray *array = dict[@"array"]; 12 block(array); 13 } 14 15 调用方法,显示 16 17 - (IBAction)blockCallBack 18 { 19 [self showArrayUsingBlock:^(NSArray *array) { 20 _outputLabel.text = array[1]; 21 }]; 22 } 23 24 三种模式都很轻松~
KVO
Kvo是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数 据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用的地方非常广泛。(这样的机制听起来类 似Notification,但是notification是需要一个发送notification的对象,一般是 notificationCenter,来通知观察者。而kvo是直接通知到观察对象。)
适用kvo时,通常遵循如下流程:
1 注册:
keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型)。
options是监听的选项,也就是说明监听泛黄的额字典包含什么值。有两个常用的选项:
NSKeyValueObservingOptionsNew 指返回的字典包含新值。
NSKeyValueObservingOptionsOld 值返回的字典包含旧值。
2 实现变化方法:
change:(NSDictionary *)change context:(void*)context
change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。
1 1 .person类 2 @implementation Person 3 @synthesize name,age;//属性name 将被监视 4 -(void) changeName 5 { 6 name=@"changeName directly"; 7 } 8 @end 9 10 11 2.PersonMonitor类 监视了name属性 12 @implementation PersonMonitor 13 14 - (void)observeValueForKeyPath:(NSString *)keyPath 15 ofObject:(id)object 16 change:(NSDictionary *)change 17 context:(void *)context 18 { 19 if ([keyPath isEqual:@"name"]) 20 { 21 NSLog(@"change happen, old:%@ new:%@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]); 22 } 23 } 24 @end 25 26 27 3测试代码 28 29 //初始化被监视对象 30 Person *p =[[Person alloc] init]; 31 //监视对象 32 PersonMonitor *pm= [[PersonMonitor alloc]init]; 33 [p addObserver:pm forKeyPath:@"name" options:(NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld) context:nil]; 34 35 //测试前的数据 36 NSLog(@"p.name is %@",p.name); 37 38 //通过setvalue 的方法,PersonMonitor的监视将被调用 39 [p setValue:@"name kvc" forKey:@"name"]; 40 41 //查看设置后的值 42 NSLog(@"p name get by kvc is %@",[p valueForKey:@"name"]); 43 44 //效果和通过setValue 是一致的 45 p.name=@"name change by .name="; 46 47 //通过person自己的函数来更改name 48 [p changeName]; 49 50 结果是 51 输出 52 2011-07-03 16:35:57.406 Cocoa[13970:903] p.name is name 53 2011-07-03 16:35:57.418 Cocoa[13970:903] change happen, old:name new:name kvc 54 2011-07-03 16:35:57.420 Cocoa[13970:903] p name get by kvc is name kvc 55 2011-07-03 16:35:57.421 Cocoa[13970:903] change happen, old:name kvc new:name change by .name=
通知:
通知需要有一个通知中心:NSNotificationCenter,自定义通知的话需要给一个名字,然后监听。
优点:通知的发送者和接受者都不需要知道对方。可以指定接收通知的具体方法。通知名可以是任何字符串。
缺点:较键值观察(KVO)需要多点代码,在删掉前必须移除监听者。
1 通知中心的方式可以不用设置代理,但是需要设置观察者和移除观察者。 2 3 4 5 代码 6 7 - (IBAction)callBack 8 { 9 NSDictionary *dict = @{@"array": @[@"Chelsea", @"MUFC", @"Real Madrid"]}; 10 NSArray *array = dict[@"array"]; 11 [[NSNotificationCenter defaultCenter] postNotificationName:@"OutputArrayNotification" object:array]; 12 } 13 14 注册和移出观察者 15 16 - (void)viewWillAppear:(BOOL)animated 17 { 18 [super viewWillAppear:animated]; 19 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outputWithNote:) name:@"OutputArrayNotification" object:nil]; 20 } 21 22 - (void)viewDidDisappear:(BOOL)animated 23 { 24 [super viewDidDisappear:animated]; 25 [[NSNotificationCenter defaultCenter] removeObserver:self name:@"OutputArrayNotification" object:nil]; 26 } 27 28 显示 29 30 - (void)outputWithNote:(NSNotification *)aNotification 31 { 32 NSArray *receiveArray = [aNotification object]; 33 _outputLabel.text = receiveArray[0]; 34 }
代理:
通过setDelegate来设置代理对象,最典型的例子是常用的TableView.
优点:支持它的类有详尽和具体信息。
缺点:该类必须支持委托。某一时间只能有一个委托连接到某一对象。
1 作为IOS中最常见的通讯模式,代理几乎无处不在。 2 3 4 5 看实例 6 这里有一个数组,我们首先通过代理的方式将数组传递到其他方法中去。 7 设置协议及方法 8 9 @protocol CallBackDelegate; 10 11 @interface ViewController : UIViewController 12 @property (weak, nonatomic) id<CallBackDelegate> delegate; 13 @end 14 15 @protocol CallBackDelegate <NSObject> 16 - (void)showArrayWithDelegate:(NSArray *)array; 17 @end 18 19 @interface ViewController () <CallBackDelegate> 20 21 点击按钮传递数组让其显示 22 23 - (IBAction)delegateCallBack 24 { 25 NSDictionary *dict = @{@"array": @[@"Chelsea", @"MUFC", @"Real Madrid"]}; 26 NSArray *array = dict[@"array"]; 27 [self.delegate showArrayWithDelegate:array]; 28 } 29 30 调用,显示 31 32 - (void)showArrayWithDelegate:(NSArray *)array 33 { 34 _outputLabel.text = array[2]; 35 } 36 37 最重要也是最容易忽略的,就是一定要设置delegate的指向。 38 完成后屏幕显示
总结:
从上面的分析中可以看出3中设计模式都有各自的优点和缺点。其实任何一种事物都是这样,问题是如何在正确的时间正确的环境下选择正确的事物。下面就讲讲如何发挥他们各自的优势,在哪种情况下使用哪种模式。注意使用任何一种模式都没有对和错,只有更适合或者不适合。 每一种模式都给对象提供一种方法来通知一个事件给其他对象,而且前者不需要知道侦听者。在这三种模式中,我认为KVO有最清晰的使用案例,而且针对某个需 求有清晰的实用性。而另外两种模式有比较相似的用处,并且经常用来给controller间进行通信。那么我们在什么情况使用其中之一呢?
根据我开发iOS应用的经历,我发现有些过分的使用通知模式。我个人不是很喜欢使用通知中心。我发现用通知中心很难把握应用的执行流程。 UserInfo dictionaries的keys到处传递导致失去了同步,而且在公共空间需要定义太多的常量。对于一个工作于现有的项目的开发者来说,如果过分的使用 通知中心,那么很难理解应用的流程。
我觉得使用命名规则好的协议和协议方法定义对于清晰的理解controllers间的通信是很容易的。努力的定义这些协议方法将增强代码的可读性,以及更好的跟踪你的app。代理协议发生改变以及实现都可通过编译器检查出来,如果没有将会在开发的过程中至少会出现crash,而不仅仅是让一些事情异常工作。甚至在同一事件通知多控制器的场景中,只要你的应用在controller层次有着良好的结构,消息将在该层次上传递。该层次能够向后传递直至让所有需要知道事件的controllers都知道。
当然会有delegation模式不适合的例外情况出现,而且notification可能更加有效。例如:应用中所有的controller需要知道一个事件。然而这些类型的场景很少出现。另外一个例子是当你建立了一个架构而且需要通知该事件给正在运行中应用。
根据经验,如果是属性层的时间,不管是在不需要编程的对象还是在紧紧绑定一个view对象的model对象,我只使用观察。对于其他的事件,我都会使用delegate模式。如果因为某种原因我不能使用delegate,首先我将估计我的app架构是否出现了严重的错误。如果没有错误,然后才使用notification。
本文转自:点击打开链接
ios开发——实用技术篇Block/KVO/通知/代理相关推荐
- IOS开发之----远程推送通知
原文地址:IOS开发之----远程推送通知作者:倒計時 玩了一年的iPhone了各种App的远程通知接收了不少,每次接收到的时候,就在反思,这丫的怎么实现的! 由于工作方面一直没有接触的机会,所以只好 ...
- iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式
说明: 1)该文简短介绍在iOS开发中遍历字典.数组和集合的几种常见方式. 2)该文对应的代码可以在下面的地址获得:https://github.com/HanGangAndHanMeimei/Cod ...
- (转)iOS开发资源:推送通知相关开源项目--PushSharp、APNS-PHP以及Pyapns等
PushSharp (github) PushSharp是一个实现了由服务器端向移动客户端推送消息的开源C#库,支持 iOS (iPhone/iPad APNS). Android (C2DM/GC ...
- iOS开发之注册推送通知权限
1.首先在工程设置开启通知权限(Push Notifications开关打开) 2.注册通知权限,在此步骤会弹出用户授权提示 #import <UserNotifications/UserNot ...
- iOS 开发实用工具
引言: 工欲善其事,必先利其器!好的辅助工具可以让我们的开发旅途事半功倍.接下来介绍几款博主目前正在使用的开发辅助工具. Tips: 好的工具大部分都是收费的,当然咯,你想不花钱就用起来,也不是不可以 ...
- iOS开发:使用Block在两个界面之间传值(Block高级用法:Block传值)
使用Block的地方很多,其中传值只是其中的一小部分,下面介绍Block在两个界面之间的传值: 先说一下思想: 首先,创建两个视图控制器,在第一个视图控制器中创建一个UILabel和一个UIButto ...
- iOS开发-多层嵌套block中如何使用__weak和__strong
1.关于__weak __weak只能在ARC模式下使用,也只能修饰对象(比如NSString等),不能修饰基本数据类型(比如int等) __weak修饰的对象在block中不可以被重新赋值. __w ...
- ios 代码设置控件宽高比_#iOS 开发实用技巧# Masonry 控件宽高(不同控件之间宽高比)比设置方法...
Masonry 项目中我们实用 Masonry 自动布局,可能需要设置控件的宽高比,需要记录一下这个方法. 一句代码搞定: 注意这里需要设置的是控件的宽高比. make.width.equalTo(s ...
- iOS开发实用工具类,助你开发一臂之力
本工具类是我经多年多项目多场景总结出来的一个满足你在任何一个项目都能使用到的一些实用方法类,使用起来超级简单,能帮助你在开发过程中节省很多时间,只需找到对应方法直接调用即可,废话少说下面就看看有哪些实 ...
- 数组反向遍历ios_iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式
iOS开发实用技巧-Objective-C中的各种遍历(迭代)方式 说明: 1)该文简短介绍在iOS开发中遍历字典.数组和集合的几种常见方式. 2)该文对应的代码可以在下面的地址获得:https:// ...
最新文章
- php mysql 获取错误_php怎样获取mysql错误信息
- 总结下用Vue.js和webpack遇到的问题
- codeforces C. Bits(数学题+或运算)
- oracle事件号,oracle8管理员账号密码Oracle-等待事件解读
- 抓包工具Charles使用教程
- android+解锁风格,Android手势解锁控件实现(仿京东金融手势解锁)
- java内存分配不够_java内存空间不够问题
- ubuntu 中 vi 编辑文件上下左右删除键毫无作用肿么办!(上上下下左右左右BABA)
- Big-Endian 和 Little-Endian 模式的区别
- Python爬虫爬取链家租房信息(python大作业)
- MATLAB绘制B样条曲线
- 电脑主要硬件解读与选购建议
- java宠物医院,基于SSM框架的JAVA宠物医院管理信息系统,源码分享
- 中国移动一级业务支撑系统多Kubernetes集群PaaS平台实践经验分享
- 【NXP出品PINS-TOOL-IMX】IMX6ULL引脚配置工具PINS-TOOL-IMX介绍
- 运维体系 ------ 技术运营
- 手把手教你MySQL 重置密码
- ubuntu安装celery报错 encountered error while generating package metadata
- IC-CAD Methodology 企业实战之 inhouse-tool 开发示例
- c语言实现按键的抖动与消除,8051单片机实验2——按键识别(一)
热门文章
- 计算机硬盘中病毒吗,硬盘中病毒能格式化吗
- 如何在华为云上服务器部署WEB网站
- 【菜鸟学习论文】2020_Wasserstein Distances for Stereo Disparity Estimation
- 通用计数器的检定方案
- [Vue][transition]Vue中实现类似JQuery中slideUp slideDown的滑动显示隐藏过渡动画效果
- CarEye GT1078 转GB28181 方案
- 【swap】swap使用过高的处理方法
- linux新增加swap空间,Linux增加swap空间的方法
- mysql: 身份证校验等问题
- ORA-12170:TNS:连接超时 详细解决方法