【原】IOS中KVO模式的解析与应用
最近老翁在项目中多处用到了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
//
// Walker.h
// KVOExample
//
// Created by 老翁 on 13-7-29.
// Copyright (c) 2013年 wzl. All rights reserved.
// #import <Foundation/Foundation.h> @interface Walker : NSObject
{
NSInteger _age;
NSString *_name;
} @property (nonatomic) NSInteger age;
@property (nonatomic, retain) NSString *name; - (id)initWithName:(NSString *)name age:(NSInteger)age; @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
//
// ViewController.m
// KVOExample
//
// Created by 老翁 on 13-7-29.
// Copyright (c) 2013年 wzl. All rights reserved.
// #import "ViewController.h" @interface ViewController () @end @implementation ViewController @synthesize walker = _walker; - (void)dealloc
{
[_walker release];
[_ageLabel release];
[super dealloc];
} - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_walker = [[Walker alloc] initWithName:@"老翁" age:];
/* 关键步骤 */
[_walker addObserver:self
forKeyPath:@"age"
options:NSKeyValueObservingOptionNew
context:nil]; //UI initialization
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(, , , )];
[btn setBackgroundColor:[UIColor lightGrayColor]];
[btn setTitle:@"增加5岁" forState:UIControlStateNormal];
[btn addTarget:self
action:@selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn]; _ageLabel = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
_ageLabel.text = [NSString stringWithFormat:@"%@现在的年龄是: %d", _walker.name, _walker.age];
_ageLabel.backgroundColor = [UIColor clearColor];
[self.view addSubview:_ageLabel]; } - (void)buttonPressed
{
_walker.age += ;
} /* KVO function, 只要object的keyPath属性发生变化,就会调用此函数*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"age"] && object == _walker) {
_ageLabel.text = [NSString stringWithFormat:@"%@现在的年龄是: %d", _walker.name, _walker.age];
}
} - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
点击了按钮之后,系统会调用 observeValueForKeyPath :函数,这个函数应该也是回调函数。在该函数内部做UI更新。我们以这种轻量级的方式达到了目的。
##################################################
声明 转载请注明原文地址:
http://www.cnblogs.com/wengzilin/p/3223770.html
欢迎私下交流学习:
QQ 719113951
##################################################
【原】IOS中KVO模式的解析与应用的更多相关文章
- IOS中KVO模式的解析与应用
IOS中KVO模式的解析与应用 最近老翁在项目中多处用到了KVO,深感这种模式的好处.现总结如下: 一.概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修 ...
- js中State模式的解析及运用
状态模式,在大的范畴中的定义为当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.每种编程语言有不同的实现方式,运用的范围也多用于游戏之中. 这里我用javascript来模拟状 ...
- iOS 中架构模式的浅显理解
我们开发软件中应用各种模式,主要是为了 职责划分:一个类只做一件事 易用,可维护,方便扩展 解耦,相互独立,可单独测试 各种设计模式其实都是在解决上面的问题,让我们对比看看吧. 一.如何理解MVC设计 ...
- [原]iOS中 Web 页面与 Native Code 的一种通信方式
在 iOS 开发中,Web 页面与 Native Code 通信可以分为两个方面: 1.Native Code 调用 Web 页面的方法:主要是调用页面中的 Javascript 函数. 2.Web ...
- iOS中UITextField 使用全面解析
//初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...
- iOS中UITextField 使用全面解析 分类: ios技术 2015-04-10 14:37 153人阅读 评论(0) 收藏
//初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...
- iOS中 KVO 键值观察者
KVO Key-Value-Obsever 键值观察者 1.首先要有一个观察者,此时被观察者是自己找一个观察者观察自己的key值对应的value值有没有改变,如果改变了就可以做一些响应的操作 创建一个 ...
- iOS边练边学--iOS中的XML数据解析
XML的解析方式 SAX 大小文件都可以 NSXMLParser DOM 最好是小文件 GDataXML NSXMLParser的用法 创建解析器来解析 // 创建XML解析器 NSXMLParser ...
- iOS边练边学--iOS中的json数据解析
JSON数据(NSData) -> OC对照表 {} -> NSDictionary @{} [] -> NSArray @[] "jack" -> NSS ...
随机推荐
- codeforces Fedor and New Game
#include<iostream> #include<stack> #include<cstring> #include<cstdio> #inclu ...
- IE下angularJS页面跳转的bug
用Angularjs做项目的过程中遇到一种情况:就是在IE浏览器下,当访问网站页面后,点击浏览器中的向左和向右(返回和前进)按钮时,需要点击两次才能正确跳转,但是在chrome及其他浏览器下该bug没 ...
- 解决debian中脚本无法使用source的问题
#!/bin/sh source scripts/common.sh 现象: shell脚本中source aaa.sh时提示 source: not found 原因: ls -l `which s ...
- MySQL+Sphinx实现全文搜索
最近在做一个搜索引擎,主要是对图书方面的对象级的搜索,首先来了解下Sphinx吧. 它能够提高你的查询的速度,这个不是一般的快. Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,Pos ...
- Sql Server来龙去脉系列之三 查询过程跟踪
我们在读写数据库文件时,当文件被读.写或者出现错误时,这些过程活动都会触发一些运行时事件.从一个用户角度来看,有些时候会关注这些事件,特别是我们调试.审核.服务维护.例如,当数据库错误出现.列数据被更 ...
- 介绍两种风格的URL
两种风格的“动态资源”——统一资源定位符(Uniform Resource Lactor,URL) 当前互联网上主要有两种主要风格的URL: 第一种直接在URL中知名文件(比如xxx.php,xxx. ...
- sql跨数据库转移
结构一样的话insert into 数据库A.dbo.TableAselect * from 数据库B.dbo.TableA 另外:nsert into DDD(字段1,字段2,字段3 .....)( ...
- C#监控USB接口
该C#代码实现监控USB接口是否有设备接入或拨出,包括多个U盘. using System; using System.IO; using System.Runtime.InteropServices ...
- EF工作中踩过的坑.
1.EF同一个linq里边不支持两个或两个以上不同dbcontext的使用,必须拆解开才能使用; ef也不支持自定义集合和dbcontext属性的混合使用. 2.如果要用用统一域账号连接databas ...
- Oracle数据库导入导出总结(dmp文件)
Oracle 10G 管理页面(Oracle Enterprise Manager 10g): http://localhost:1158/em http://localhost:1158/em/co ...