美文网首页iOS开发
iOS 反 KVO(如何知道属性被监听了)

iOS 反 KVO(如何知道属性被监听了)

作者: chenyu1520 | 来源:发表于2018-01-30 18:29 被阅读1050次

在 iOS 开发中监听一个对象的某个属性,很容易做到,然后有时候我们在写一些安全性的代码或者框架时,不想让别人监听我的某个属性怎么做呢?

有一个做法,hook 掉系统的 addObserver 方法,在这里判断 keyPath 是否是不想让监听的属性。

具体代码如下:

#import <objc/runtime.h>

@implementation NSObject (CYKVO)

+ (void)load
{
    [self switchMethod];
}

// 交换后的方法
- (void)cy_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
    @try {
        if ([keyPath isEqualToString:@"can_not_observer_name"]) {
            return;
        }
        [self cy_addObserver:observer forKeyPath:keyPath options:options context:context];
    } @catch (NSException *exception) {}
}

+ (void)switchMethod
{
    SEL cyAddSel = @selector(cy_addObserver:forKeyPath:options:context:);
    SEL sysAddSel = @selector(addObserver:forKeyPath:options:context:);
    
    Method cyAddMethod = class_getClassMethod([self class],cyAddSel);
    Method sysAddMethod = class_getClassMethod([self class], sysAddSel);
    
    method_exchangeImplementations(cyAddMethod, sysAddMethod);
}

@end

具体使用场景可能是这样的:
有一个类是这样写的:

//.h
@interface Person : NSObject

@property (nonatomic, strong) NSString *can_not_observer_name;

@end

//.m
@implementation Person

-(instancetype)init {
    self = [super init];
    self.can_not_observer_name = @"name";
    
    return self;
}

@end

在某个 VC 里这样使用:

@interface ViewController ()
@property (nonatomic, strong)Person *person;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.person = [[Person alloc] init];
    [self.person addObserver:self forKeyPath:@"can_not_observer_name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"observeValueForKeyPath");
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.person.can_not_observer_name = @"set a new value";
}

@end

这样是监听不到 can_not_observer_name 这个属性的。

相关文章

  • iOS 反 KVO(如何知道属性被监听了)

    在 iOS 开发中监听一个对象的某个属性,很容易做到,然后有时候我们在写一些安全性的代码或者框架时,不想让别人监听...

  • iOS原理(二)----KVO,KVC

    iOS原理(二)----KVO,KVC KVO KVO的全称是Key-Value Observing,俗称“键值监...

  • 关于KVO的那些事 之 KVO安全用法封装

    关于KVO的那些事 之 KVO安全用法封装 KVO (Key Value Observering) 是iOS用于监...

  • 如何对NSMutableArray进行KVO

    我们知道,iOS 中 KVO (key-value-observing) 的原理,简单来说就是重写了被观察属性的 ...

  • Objective-C的本质(4)—— KVO本质

    参考:iOS底层原理总结 - 探寻KVO本质iOS-KVO本质 问题一:kvo如果找到对应的属性 KVO不存在查找...

  • KVO总结

    KVO的全称是Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变 查看被监...

  • OC的KVO学习记录(1)

    KVO :键值观察。当我们需要对某个对象的某个属性进行监听的时候,我们就利用KVO机制,通过属性关键字绑定,进行监...

  • 使用Block实现KVO

    在iOS开发中,我们可以通过KVO机制来监听某个对象的某个属性的变化。 用过KVO的同学都应该知道,KVO的回调是...

  • iOS KVO 基础与底层原理

    iOS KVO 基础与底层原理 KVO基础 KVO是通过给对象object的属性property注册observe...

  • iOS NSMutableArray KVO

    iOS 中 KVO (key-value-observing) 的原理,简单来说就是重写了被观察属性的 set 方...

网友评论

    本文标题:iOS 反 KVO(如何知道属性被监听了)

    本文链接:https://www.haomeiwen.com/subject/lanczxtx.html