KVO是一种设计模式,名为观察者.

addObserver:forKeyPath:options:context:

通知其他对象的方法,这个方法在NSObject中就已经申明了,也就是说任何继承自NSObject的对象都可以使用KVO.

我们来实现一个对象a值改变的时候去通知对象b.

新建两个ModelA ModelB 类.

ModelA.h + ModelA.m

#import <Foundation/Foundation.h>

@interface ModelA : NSObject

@property (nonatomic, strong) NSString *name;

@end
#import "ModelA.h"

@implementation ModelA

@end

ModelB.h + ModelB.m

#import <Foundation/Foundation.h>

@interface ModelB : NSObject

@property (nonatomic, strong) NSString *sex;

@end
#import "ModelB.h"

@implementation ModelB

-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
self.sex = @"female";
} @end

请将如下延时执行的代码添加进工程当中

- (void)delay:(int64_t)delta execute:(dispatch_block_t)block
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta * NSEC_PER_SEC),
dispatch_get_main_queue(), block);
}

然后再写如下的代码:

执行结果如下:

2014-05-06 17:40:35.346 FileManager[20208:60b] Application windows are expected to have a root view controller at the end of application launch
2014-05-06 17:40:37.347 FileManager[20208:60b] female

如果注释掉ModelB中的方法observeValueForKeyPath:ofObject:change:context:,运行时会导致崩溃:

如果重复移除了两次,也会导致崩溃-_-!!!!

也就是这么一层关系:

A对象要通知B对象,B对象必须实现监听的方法,否则一旦有消息发送就会导致崩溃.

A对象不想通知B对象了,需要从B对象身上移除掉通知.

要想程序不出现问题,我们需要实现3步.

(主动添加B的通知) A -------> B(不实现一个方法就崩溃)

(主动移除B的通知) A ---X-->  B

(重复移除B的通知) A ---X-->  B(崩溃)

用起来很恶性,还好,我们可以重复添加B的通知而不崩溃......

问题:在ARC中我们需要移除KVO的observer么?

You should explicitly remove the observer even you use ARC. Create a dealloc method and remove there..

-(void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self];}

If you see the method you don't need to call [super dealloc]; here, only the method without super dealloc needed.

你需要非常明确的移除你的通知者,即使是在ARC中.创建一个dealloc方法然后在方法里面移除.

ARC中你不需要调用[super dealloc].

问题:ARC给一个对象添加了observer有可能会导致循环应用什么的么?

You need to call removeObserver, ARC only automates retain counts. removeObserver does not impact the retain count.

你需要调用removeObserver,ARC只是自动管理了retain counts,removeObserver并不影响retain count.(这一点我不确定,有待验证)

问题:当要通知的对象已经nil了,这个通知会自动移除吗?

Observers are not removed automatically. From the NSNotificationCenter Class Reference:

观察者不会自动移除,请查看NSNotificationCenter类的原文引述:

Important: The notification center does not retain its observers, therefore, you must ensure that you unregister observers (using removeObserver: or removeObserver:name:object:) before they are deallocated. (If you don't, you will generate a runtime error if the center sends a message to a freed object.)

很重要:通知中心并不会retain他的观察者,所以,你必须确保你那些对象销毁之前注销掉观察者,否则就会出现错误.

You should therefore call

[[NSNotificationCenter defaultCenter] removeObserver:self];

in your dealloc method if you are not 100% sure that the observer was not removed previously.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html#//apple_ref/occ/instm/NSObject/addObserver%3aforKeyPath%3aoptions%3acontext%3a

addObserver:forKeyPath:options:context:

Registers anObserver to receive KVO notifications for the specified key-path relative to the receiver.

- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
Parameters
anObserver

The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:.

keyPath

The key path, relative to the receiver, of the property to observe. This value must not be nil.

options

A combination of the NSKeyValueObservingOptions values that specifies what is included in observation notifications. For possible values, see “NSKeyValueObservingOptions.”

context

Arbitrary data that is passed to anObserver in observeValueForKeyPath:ofObject:change:context:.

Discussion

KVO等具体实现步骤以及注意事项的更多相关文章

  1. 【Azure Redis 缓存 Azure Cache For Redis】Azure Redis由低级别(C)升级到高级别(P)的步骤和注意事项, 及对用户现有应用的潜在影响,是否需要停机时间窗口,以及这个时间窗口需要多少的预估问题

    问题描述 由于Azure Redis的性能在不同级别表现不同,当需要升级/缩放Redis的时候,从使用者的角度,需要知道有那些步骤? 注意事项? 潜在影响?停机事件窗口? 升级预估时间? 解决方案 从 ...

  2. spring4+hibernate4+struts2项目整合的步骤及注意事项

    首先,在整合框架之前,我们需要知道Spring框架在普通Java project和Web project中是略有不同的. 这个不同地方就在于创建IOC容器实例的方式不同,在普通java工程中,可以在m ...

  3. 自定义Camera综述(一般步骤、注意事项、遇到的难题<【内存溢出问题】>、像素参考)

    一般步骤: 1. 检查和访问Camera:创建代码来检查Camera和所申请访问的存在性: 2. 创建一个预览类:继承SurfaceView来创建一个Camera的预览类,并实现SurfaceHold ...

  4. cocos2d-x笔记2: 编译到安卓的步骤与注意事项

    博客地址: www.cnblogs.com/wolfred7464/ 不得不说,真心复杂,本篇博客总结的基本是最简最直接的步骤了,不用Cygwin和Ant的,当然用也可以... 以下用 %PROJEC ...

  5. redis cluster 集群搭建步骤和注意事项

    1.安装Ubuntu ,修改root的密码. sudo passwd  (apt-get update 更新系统) 2.安装 Gcc 和G++  sudo apt-get install build- ...

  6. 简单使用Vuex步骤及注意事项

    使用Vuex的步骤: (1)安装: 1.使用npm安装: npm install vuex --save 2.使用script标签引入 <script src="/path/to/vu ...

  7. 整合struts2+hibernate详细配置步骤及注意事项

    刚刚学完这两个框架,就迫不及待的做了一个例子,在整合两个框架的时候,也碰到了一些小问题,下面介绍一下配置的步骤: 1.创建一个自定义的struts2和hibernate的类库 因为之前写例子都是直接将 ...

  8. 给11gR2 Dataguard打psu补丁的步骤及注意事项

    参考文档278641.1 0.备份备主备库的spfile备份主库的数据 1.在主库上暂停向备库传日志alter system set log_archive_dest_state_X=defer sc ...

  9. MySQL主备停机步骤与注意事项

    双十一马上到了,一堆的事情,今天登录mysql数据库服务器的时候突然发现服务器时间戳不对,比北京时间快了几分钟,我的天...随后检查了其他的几台数据库服务器发现同样都存在不同的偏差,最小的比北京时间快 ...

随机推荐

  1. Tomcat多域名访问

    对于域名解析相信很多小伙伴都了解过,就是我们在万网购买一个域名,比如hpugs.com,然后呢?我们希望域名与我们的服务器绑定,然后通过域名直接访问我们的项目,这就是本篇要和大家一起探讨的问题.下面开 ...

  2. JavaWeb框架SSH_Struts2_(三)

    1. Struts2的拦截器(使用拦截器实现权限控制) 拦截器简介 拦截器概述 拦截器工作原理 拦截器的配置 Struts2的内建拦截器 内建拦截器的介绍 内建拦截器的配置 自定义拦截器 实现自定义拦 ...

  3. c语言的typedef

    一.typedef作用简介 1.作用:给已经存在的类型起一个新的名称 2.使用场合: 1> 基本数据类型 2> 指针 3> 结构体 4> 枚举 5> 指向函数的指针 * ...

  4. Javascript 常用类型检测

    1.判断变量是否为数组的数据类型? 方法一 :判断其是否具有"数组性质",如slice()方法.可自己给该变量定义slice方法,故有时会失效. 方法二 :obj instance ...

  5. 制作支持 BIOS+UEFI 的 U 盘 grub2+bootmgr 引导 + deepin_recovery + deepin_iso + win_pe

    网盘下载:https://pan.baidu.com/s/1c2GXPo0 U盘为 FAT32,MBR分区表 1.下载:U盘grub2+bootmgr引导2017.12.6.2.7z 2.解压到 U盘 ...

  6. Windows下根据端口号查找进程并关闭

    经常用到,但是总记不住命令,备忘一下…… netstat -aon|findstr "8080"  找到进程号 tasklist|findstr "7200"  ...

  7. pku 1330 Nearest Common Ancestors LCA离线

    pku 1330 Nearest Common Ancestors 题目链接: http://poj.org/problem?id=1330 题目大意: 给定一棵树的边关系,注意是有向边,因为这个WA ...

  8. Web 动画帧率(FPS)计算

    我们知道,动画其实是由一帧一帧的图像构成的.有 Web 动画那么就会存在该动画在播放运行时的帧率.而帧率在不同设备不同情况下又是不一样的. 有的时候,一些复杂或者重要动画,我们需要实时监控它们的帧率, ...

  9. cronlog分割tomcat catalina.out日志

    Tomcat 下日志文件 catalina.out 过大,几百兆或几个G,进而造成再也无法写入更多的日志内容,至使 Tomcat 无法处理请求,所以依靠cronlog来分割: 具体步骤如下: 1.安装 ...

  10. Java基础(十一) Stream I/O and Files

    Java基础(十一) Stream I/O and Files 1. 流的概念 程序的主要任务是操纵数据.在Java中,把一组有序的数据序列称为流. 依据操作的方向,能够把流分为输入流和输出流两种.程 ...