最近老翁在项目中多处用到了KVO,深感这种模式的好处。现总结如下:

一、概述

KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。

KVO其实也是“观察者”设计模式的一种应用。我的看法是,这种模式有利于两个类间的解耦合,尤其是对于 业务逻辑与视图控制 这两个功能的解耦合。

二、引子

先来看个引子:

有一个业务类:Walker,在这个类内部只负责关于业务逻辑的处理,比如负责从服务器传来的JSON中解析数据,或做其他业务数据上的处理。

有另一个类:ViewController,专门负责界面的交互与试图更新。其中,需要讲Walker的某些属性显示出来,并实时更新。

目前,据我所能想到的方法有以下几种:

方法1、直接的函数调用

在Walker的类内部,把创建一个ViewController的对象,然后调用ViewController的修改界面的方法,把需要改动的属性值作为形参传给该函数。

这种方式最直观,因为它不需要绕任何弯子。但是,确实最糟的方法。因为Walker与ViewController这两个类从此紧紧耦合在一起了。记住这句话,处理业务逻辑的类,对外部的事情知道得越少越好。甚至于,要做到外部是否有VC(View Controller),有多少个VC都不影响我。假设这是一个项目,程序员A负责业务逻辑的处理,程序员B负责UI,则采取这种方式后,程序员A就受制于B,互相干扰。

方法2、利用消息通信机制(NSNotification)

在Walker内部建立消息中心NSNotificationCenter,把实例化之后的VC对象作为observer。Center建在Walker或者VC都无所谓,具体看我博客的另一篇文章【NSNotificationCenter总结】。这种方法比前面的方法好一些。但是有一个很大的缺点:如果Walker需要更改的属性很多而且很频繁,那么这种方式很不方便传值。而且,注意到了没,“把实例化后的VC对象作为observer”,始终逃不开在Walker内部对VC实例化。依旧是耦合着。

方法3、利用delegate

关于delegate的介绍有很多,这里就不多讲。但是在这种需求下用 delegate,有点“杀鸡用牛刀”感觉,成本较大,而且不直观。

方法4、利用KVO模式

所有的代码都将在ViewController中实现。对于Walker,它自己都不知道外部是否有VC,以及VC会怎用用我的属性。

三、Demo

 1 //
 2 //  Walker.h
 3 //  KVOExample
 4 //
 5 //  Created by 老翁 on 13-7-29.
 6 //  Copyright (c) 2013年 wzl. All rights reserved.
 7 //
 8
 9 #import <Foundation/Foundation.h>
10
11 @interface Walker : NSObject
12 {
13     NSInteger _age;
14     NSString *_name;
15 }
16
17 @property (nonatomic) NSInteger age;
18 @property (nonatomic, retain) NSString *name;
19
20 - (id)initWithName:(NSString *)name age:(NSInteger)age;
21
22
23 @end
#import "Walker.h"@implementation Walker@synthesize age = _age;
@synthesize name = _name;- (void)dealloc
{[_name release];[super dealloc];
}- (id)initWithName:(NSString *)name age:(NSInteger)age
{if (self = [super init]) {_name = name;_age = age;}return  self;
}@end

ViewController代码:

//
//  ViewController.h
//  KVOExample
//
//  Created by 老翁 on 13-7-29.
//  Copyright (c) 2013年 wzl. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "Walker.h"@class Walker;@interface ViewController : UIViewController
{Walker *_walker;UILabel *_ageLabel;
}@property (nonatomic, assign) Walker *walker;@end
 1 //
 2 //  ViewController.m
 3 //  KVOExample
 4 //
 5 //  Created by 老翁 on 13-7-29.
 6 //  Copyright (c) 2013年 wzl. All rights reserved.
 7 //
 8
 9 #import "ViewController.h"
10
11 @interface ViewController ()
12
13 @end
14
15 @implementation ViewController
16
17 @synthesize walker = _walker;
18
19
20 - (void)dealloc
21 {
22     [_walker release];
23     [_ageLabel release];
24     [super dealloc];
25 }
26
27 - (void)viewDidLoad
28 {
29     [super viewDidLoad];
30     // Do any additional setup after loading the view, typically from a nib.
31     _walker = [[Walker alloc] initWithName:@"老翁" age:25];
32     /* 关键步骤 */
33     [_walker addObserver:self
34               forKeyPath:@"age"
35                  options:NSKeyValueObservingOptionNew
36                  context:nil];
37
38
39     //UI initialization
40     UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
41     [btn setFrame:CGRectMake(120, 200, 100, 35)];
42     [btn setBackgroundColor:[UIColor lightGrayColor]];
43     [btn setTitle:@"增加5岁" forState:UIControlStateNormal];
44     [btn addTarget:self
45             action:@selector(buttonPressed)
46   forControlEvents:UIControlEventTouchUpInside];
47     [self.view addSubview:btn];
48
49     _ageLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 150, 200, 35)];
50     _ageLabel.text = [NSString stringWithFormat:@"%@现在的年龄是: %d", _walker.name, _walker.age];
51     _ageLabel.backgroundColor = [UIColor clearColor];
52     [self.view addSubview:_ageLabel];
53
54
55 }
56
57 - (void)buttonPressed
58 {
59     _walker.age += 5;
60 }
61
62 /* KVO function, 只要object的keyPath属性发生变化,就会调用此函数*/
63 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
64 {
65     if ([keyPath isEqualToString:@"age"] && object == _walker) {
66         _ageLabel.text = [NSString stringWithFormat:@"%@现在的年龄是: %d", _walker.name, _walker.age];
67     }
68 }
69
70
71
72 - (void)didReceiveMemoryWarning
73 {
74     [super didReceiveMemoryWarning];
75     // Dispose of any resources that can be recreated.
76 }
77
78 @end

点击了按钮之后,系统会调用 observeValueForKeyPath :函数,这个函数应该也是回调函数。在该函数内部做UI更新。我们以这种轻量级的方式达到了目的。

##################################################

声明 转载请注明原文地址:

http://www.cnblogs.com/wengzilin/p/3223770.html

欢迎私下交流学习:

QQ 719113951

##################################################

iOS中KVO模式的解析与应用相关推荐

  1. IOS中JSON数据的解析

    IOS中JSON数据解析 官方为我们提供的解析JSON数据的类是NSJSONSerialization,首先我们先来看下这个类的几个方法: + (BOOL)isValidJSONObject:(id) ...

  2. 8 iOS中KVO 的本质

    前言本质 Automatic key-value observing is implemented using a technique called isa-swizzling 这计划的意思就是 自动 ...

  3. IOS中四种json解析效率比较

    作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此"http://www.bejson.com/"网站来进 ...

  4. iOS中UITextField 使用全面解析

    //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, ...

  5. IOS中策略模式初运用

    前段时间项目中涉及到输入验证比较多,有简单的是否为纯数字输入的验证,是否为纯字母输入的验证,也有复杂的正则检查验证. 偶尔翻阅去年买的一本设计模式的书,看到了一种设计模式:策略模式. 运用策略模式,把 ...

  6. iOS边练边学--iOS中的XML数据解析

    XML的解析方式 SAX 大小文件都可以 NSXMLParser DOM 最好是小文件 GDataXML NSXMLParser的用法 创建解析器来解析 // 创建XML解析器 NSXMLParser ...

  7. iOS中游客模式的自动登录“正确姿势”

    正确的自动登录"姿势" 1.直接进入App首页 2.验证本地是否有accessToken缓存,如果没有,present出登录界面 3.有缓存的情况下不用去讨论自动登陆者用户名或者密 ...

  8. iOS开发系列--UITableView全面解析

    iOS开发系列--UITableView全面解析 2014-08-23 23:20 by KenshinCui, 2202 阅读, 18 评论, 收藏,  编辑 --UIKit之UITableView ...

  9. iOS 中 XML 数据交换格式

         XML 是一种自描述的数据交换格式,但是 XML 的数据交换格式并没有 JSON 来的轻便,但是无可否认的是,XML 的应用范围也是非常广泛的,比如在 ROS(一个开源机器人操作系统)中利用 ...

最新文章

  1. html中表格自动换行
  2. 使用Nginx自带的Realip模块获取用户真实IP
  3. mysql 查询slow log状态,MySQL开启慢查询日志log-slow-queries的方法
  4. 从零认识单片机(9)
  5. sp烘焙流程_次世代86机甲战神制作全流程
  6. JavaScript高级之构造函数和原型
  7. 使用TweenMax更方便的创建连续的运动。
  8. 红橙Darren视频笔记 自定义View总集篇
  9. 57. TCP relay功能描述及Python实现
  10. Visio2010绘制用例图
  11. 采集摄像头RGB565数据并转为bmp图像
  12. 2020计算机二级c语言答案,2020年全国计算机二级C语言考试试题分析
  13. 全志A33N切换分支.repo/repo/repo forall -c git checkout exdroid-7.1.1_r23-a33-v7.0rc2.1
  14. Linux下的hostid
  15. 学习笔记96—WIN7/WIN8/WIN10 安装 MSDE SQL2000 卡住不动的解决办法
  16. RN如何使用原生的AndroidUI组件
  17. 如何快速拷贝整个网站所有网页
  18. 小程序定制开发收费标准
  19. RabbitMQ 设置消息的TTL(过期时间)
  20. 2022“杭电杯”中国大学生算法设计超级联赛(4)

热门文章

  1. Centos 修改时间地区及NTP同步北京时间
  2. JavaScript 中的有限状态机
  3. Javascript导出Excel的方法
  4. 用Asp.net 传送大文件
  5. HTMLButton控件下的Confirm()
  6. 浅谈无缓存I/O操作和标准I/O文件操作区别 (转载)
  7. Python3中装饰器介绍
  8. 海思3559A上编译FFmpeg源码操作步骤
  9. C++11中头文件thread的使用
  10. 一维码Code 128简介及其解码实现(zxing-cpp)