简洁的KVO -- 使用Block响应事件
涉及内容:
KVO,Runtime,Category,Block
首先创建NSObject的Category
举个例子是这样的:

随后定义你需要响应的Block结构
我简单一点就这样咯
typedef void(^NickyObserverBlock)(id oldValue,id newValue);
添加方法
- (void)setObserveKeyPath:(id)keypath signal:(NSString *)sign didChangedBlock:(NickyObserverBlock)block;
keypath就不解释了,singal是标识
标识存在的意义是 在多个observe中 对同一个对象监听时 作为区分作用
随后往NSObject里添加一个字典对象 用作存储 对象设置的block和keypath+signal
字典的key为 keypath+signal object为block
随后实现上面定义的setObserve方法
- (void)setObserveKeyPath:(id)keypath signal:(NSString *)sign didChangedBlock:(NickyObserverBlock)block{
[self.changeBlockMaps setObject:block forKey:[NSString stringWithFormat:@"%@%p",keypath,&sign]];
[self addObserver:self forKeyPath:keypath options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:&sign];
}
在实现方法 里,对象给自己添加KVO,同时设置keypath及context,context必须设置,不然后面在kvo响应里无法取到我们字典里存储的block
然后实现kvo事件:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
NSString *path = [NSString stringWithFormat:@"%@%p",keyPath,context];
NickyObserverBlock block = [self.changeBlockMaps objectForKey:path];
if (block){
block(change[@"old"],change[@"new"]);
}
}
path为前面设置时拼接的keypath+signal
取到里面的block对象,并执行
到最后 请不要忘记对象销毁时手动把observe remove掉(虽然ios10之后不remove也不会崩...)..
完整的category:
.h
#import <Foundation/Foundation.h>
typedef void(^NickyObserverBlock)(id oldValue,id newValue);
@interface NSObject (NickyKVO)
- (void)setObserveKeyPath:(id)keypath didChangedBlock:(NickyObserverBlock)block;
- (void)setObserveKeyPath:(id)keypath signal:(NSString *)sign didChangedBlock:(NickyObserverBlock)block; @end
.m
//
// NSObject+NickyKVO.m
// KvoDemo
//
// Created by NickyTsui on 2018/3/30.
// Copyright © 2018年 nickytsui. All rights reserved.
// #import "NSObject+NickyKVO.h"
#import <objc/runtime.h>
@interface NSObject()
@property (strong,nonatomic) NSMutableDictionary <NSString *,NickyObserverBlock> *changeBlockMaps;
@end @implementation NSObject (NickyKVO)
- (void)setObserveKeyPath:(id)keypath signal:(NSString *)sign didChangedBlock:(NickyObserverBlock)block{
[self.changeBlockMaps setObject:block forKey:[NSString stringWithFormat:@"%@%p",keypath,&sign]];
[self addObserver:self forKeyPath:keypath options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:&sign];
}
- (void)setObserveKeyPath:(id)keypath didChangedBlock:(NickyObserverBlock)block{
[self setObserveKeyPath:keypath signal:@"" didChangedBlock:block];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
NSString *path = [NSString stringWithFormat:@"%@%p",keyPath,context];
NickyObserverBlock block = [self.changeBlockMaps objectForKey:path];
if (block){
block(change[@"old"],change[@"new"]);
}
} - (NSMutableDictionary<NSString *,NickyObserverBlock> *)changeBlockMaps{
NSMutableDictionary<NSString *,NickyObserverBlock> * maps = objc_getAssociatedObject(self,_cmd);
if (!maps){
maps = [[NSMutableDictionary alloc]init];
self.changeBlockMaps = maps;
}
return maps;
}
- (void)setChangeBlockMaps:(NSMutableDictionary *)changeBlockMaps{
objc_setAssociatedObject(self, @selector(changeBlockMaps), changeBlockMaps, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
@end
另外 这里涉及Category里创建一个property相关问题,可以看看博客前面的文章.
简洁的KVO -- 使用Block响应事件的更多相关文章
- 「iOS造轮子」之UIButton 用Block响应事件
俗语说 一个不懒的程序员不是好程序员 造轮子,也只是为了以后更好的coding. coding,简易明了的代码更是所有程序员都希望看到的 无论是看自己的代码,还是接手别人的代码 都希望一看都知道这代码 ...
- 用block响应button的点击事件
1.继承UIButton : 2.在自己定义的button类中的方法 addTarget:(id)target action:(SEL)action forControlEvents:(UIContr ...
- 用block做事件回调来简化代码,提高开发效率
我们在自定义view的时候,通常要考虑view的封装复用,所以如何把view的事件回调给Controller就是个需要好好考虑的问题, 一般来说,可选的方式主要有target-action和de ...
- iOS 之单例,代理,通知,KVO,Block全能解析
//单例 //.h + (Instannce *)shareInstance; //.m static Instannce *instance = nil; @implementation Insta ...
- UIView独占响应事件
exclusiveTouch A Boolean value that indicates whether the receiver handles touch events exclusively. ...
- 让超出父视图范围的子视图响应事件,在UIView范围外响应点击
/** * 在父视图中重写该方法,这样可使超出部分响应事件. */ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { ...
- 解决UIButton 连续点击重复响应事件问题
经常会遇到重复点击某个按钮 事件被响应多次的情景, 有时候可能对程序本身并没有什么影响 , 可有时候偏偏需要限制button响应事件直接的间隔 . 方法一 : 标记 1 . 利用空闲enable属性来 ...
- CSS鼠标响应事件经过、移动、点击示例介绍
本文为大家介绍下CSS 鼠标响应事件:鼠标经过CSS.鼠标移动CSS.鼠标点击CSS以及示例,喜欢的朋友可以参考下 几种鼠标触发CSS事件. 说明: onMouseDown 按下鼠标时触发 onM ...
- android通知栏Notification点击,取消,清除响应事件
主要是检测android通知栏的三种状态的响应事件 这次在实现推送需求的时候,要用到android通知栏Notification点击后进入消息页面,因为要实现一个保存推送用户名字的功能,我在点击后处理 ...
随机推荐
- Map集合的几种遍历方式
Map<String ,String> map=new HashMap<String,String>(); map.put("1","value1 ...
- 读取文件中的每行数据,并且存入到list中
有一个txt文件,每行都有数据,将每行的数据转换成list列表 例如: 5,6,7,8,1 9,1,3,4 如下实现: f = open('test1.txt','r') for i in f.rea ...
- node安装升级npm
安装npm npm上有很多优秀的nodejs包,来解决常见的一些问题,比如用node-mysql,就可以方便通过nodejs链接到mysql,进行数据库的操作 在开发过程往往会需要用到其他的包,使用n ...
- 库&框架-----CDN网络引用总结
百度jquery引用地址 http://apps.bdimg.com/libs/jquery/1.6.4/jquery.js http://apps.bdimg.com/libs/jquery/1.6 ...
- dfs,bfs的二分匹配模板(模板题hdu1150)
如果不懂匈牙利算法,请点击:该趣味算法http://blog.csdn.net/dark_scope/article/details/8880547 模板: //DFS版本下的二分匹配算法 http: ...
- poj1564
dfs判重 #include<stdio.h> #include<iostream> #include<cstdio> #include<queue> ...
- Sublime Text3 配置C++(附oj刷题常用模板)
# 下载对应平台的sublime sublime最新版下载, 字体样式个人喜欢Consolas, 另附注册码: -– BEGIN LICENSE -– TwitterInc 200 User Lice ...
- Salazar Slytherin's Locket CodeForces - 855E
Salazar Slytherin's Locket CodeForces - 855E http://www.cnblogs.com/ftae/p/7590187.html 数位dp: http:/ ...
- Java 修改编码格式的几种方式
1.工作空间 workspase Window→Preferences→General→Workspace→Text file encoding→other→UTF-8 2.项目编码格式 右键项目名→ ...
- oracle 10g standby 设置
##########sample alter system set log_archive_dest_1 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST' scope=bo ...