.h 文件
#import <Foundation/Foundation.h>
typedef void (^LGFKVOBlock)(NSDictionary *change, void *context);
@interface NSObject (LGFKVOBlocks)
#pragma mark - 给某个 NSObject 注册KVO监听 使用block进行回调
/**
@param observer 监听对象
@param keyPath 监听 属性 key 值
@param options NSKeyValueObservingOptions
@param context 附带内容
@param block block回调
*/
+ (void)lgf_AddObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
withBlock:(LGFKVOBlock)block;
#pragma mark - 删除某个 NSObject 的 KVO BLOCK 监听
/**
@param observer 监听对象
@param keyPath 监听 属性 key 值
*/
+ (void)lgf_RemoveBlockObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath;
#pragma mark - 给自己注册KVO监听 使用block进行回调
/**
@param keyPath 监听 属性 key 值
@param options NSKeyValueObservingOptions
@param context 附带内容
@param block block回调
*/
- (void)lgf_AddObserverForKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
withBlock:(LGFKVOBlock)block;
#pragma mark - 删除自己的 KVO BLOCK 监听
/**
@param keyPath 监听 属性 key 值
*/
- (void)lgf_RemoveBlockObserverForKeyPath:(NSString *)keyPath;
@end
.m 文件
#import "NSObject+LGFKVOBlocks.h"
#import "LGFOCTool.h"
@implementation NSObject (LGFKVOBlocks)
#pragma mark - 给某个 NSObject 注册KVO监听 使用block进行回调
/**
@param observer 监听对象
@param keyPath 监听 属性 key 值
@param options NSKeyValueObservingOptions
@param context 附带内容
@param block block回调
*/
+ (void)lgf_AddObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
withBlock:(LGFKVOBlock)block {
objc_setAssociatedObject(observer, (__bridge const void *)(keyPath), block, OBJC_ASSOCIATION_COPY);
[self addObserver:observer forKeyPath:keyPath options:options context:context];
}
#pragma mark - 删除某个 NSObject 的 KVO BLOCK 监听
/**
@param observer 监听对象
@param keyPath 监听 属性 key 值
*/
+ (void)lgf_RemoveBlockObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath {
objc_setAssociatedObject(observer, (__bridge const void *)(keyPath), nil, OBJC_ASSOCIATION_COPY);
[self removeObserver:observer forKeyPath:keyPath];
}
#pragma mark - 给自己注册KVO监听 使用block进行回调
/**
@param keyPath 监听 属性 key 值
@param options NSKeyValueObservingOptions
@param context 附带内容
@param block block回调
*/
- (void)lgf_AddObserverForKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
withBlock:(LGFKVOBlock)block {
objc_setAssociatedObject(self, (__bridge const void *)(keyPath), block, OBJC_ASSOCIATION_COPY);
[self addObserver:self forKeyPath:keyPath options:options context:context];
}
#pragma mark - 删除自己的 KVO BLOCK 监听
/**
@param keyPath 监听 属性 key 值
*/
- (void)lgf_RemoveBlockObserverForKeyPath:(NSString *)keyPath {
objc_setAssociatedObject(self, (__bridge const void *)(keyPath), nil, OBJC_ASSOCIATION_COPY);
[self removeObserver:self forKeyPath:keyPath];
}
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL observeValueForKeyPath = @selector(observeValueForKeyPath:ofObject:change:context:);
SEL lgf_ObserveValueForKeyPath = @selector(lgf_ObserveValueForKeyPath:ofObject:change:context:);
[LGFAllMethod lgf_MethodReplaceWithClass:class selOne:observeValueForKeyPath selTwo:lgf_ObserveValueForKeyPath];
});
}
- (void)lgf_ObserveValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
LGFKVOBlock block = objc_getAssociatedObject(self, (__bridge const void *)(keyPath));
block(change, context);
}
@end
分类中方法必须替换
[LGFAllMethod lgf_MethodReplaceWithClass:class selOne:observeValueForKeyPath selTwo:lgf_ObserveValueForKeyPath];
#pragma mark - 运行时方法替换
/**
@param class 方法所属的类
@param selOne 被替换的方法
@param selTwo 替换的方法
*/
+ (void)lgf_MethodReplaceWithClass:(Class)class selOne:(SEL)selOne selTwo:(SEL)selTwo {
Method met_One = class_getInstanceMethod(class, selOne);
Method met_Two = class_getInstanceMethod(class, selTwo);
BOOL didAddMethod =
class_addMethod(class, selOne, method_getImplementation(met_Two), method_getTypeEncoding(met_Two));
if (didAddMethod) {
class_replaceMethod(class, selTwo, method_getImplementation(met_One), method_getTypeEncoding(met_One));
} else {
method_exchangeImplementations(met_One, met_Two);
}
}
以上 新建类复制黏贴即可
网友评论