简洁的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点击后进入消息页面,因为要实现一个保存推送用户名字的功能,我在点击后处理 ...
随机推荐
- May Challenge 2017
Chef and his daily routine 分析:水题,设置优先级,判断如果后面小于前面就输出no #include "iostream" #include " ...
- 最浅谈的SG函数
[更新] Nim游戏的经验: 每次最多取m个——%(m+1) 阶梯nim——奇数位无视,看偶数位互相独立,成一堆一堆的石子 . . . . 既然被征召去汇总算法..那么挑个简单点的SG函数好了.. 介 ...
- javascript之常遇到的浏览器兼容问题和解决方法
转自http://www.cnblogs.com/duenyang/p/6066737.html 常遇到的关于浏览器的宽高问题: var winW=document.body.clientWidth| ...
- 6-13 Hog特征1
Hog特征与Haar特征有点不同,Hog特征是直接经过模板计算得到的
- hadoop推荐
hadoop官网 我以Hadoop 2.7.3为例. hadoop 2.7.3 官网 . 用的操作系统是64bit Ubuntu14.04. 其中我们还可以学习 Apache Maven Proje ...
- poj 1186 方程的解数【折半dfs+hash】
折半搜索,map会T所以用hash表来存状态 #include<iostream> #include<cstdio> #include<map> using nam ...
- 《编译原理》-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法
<编译原理>-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 此编译原理确定某高级程序设计语言编译原理,理论基础,学习笔记 本笔记是对教材< ...
- 【HDU - 1257】最少拦截系统(贪心)
最少拦截系统 Descriptions: 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的 ...
- offsetLeft 与 left的区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 使用statement接口实现增,删,改操作