我的 isa-swizzling 打破了 KVO

Posted

技术标签:

【中文标题】我的 isa-swizzling 打破了 KVO【英文标题】:My isa-swizzling breaks KVO 【发布时间】:2012-06-27 07:11:38 【问题描述】:

我正在尝试实现 isa swizzling,因为我需要在某些对象的 dealloc 方法中发生一些操作。我正在覆盖 - (Class)class;返回原始类的方法(如 KVO 所做的那样)。一切正常,直到我尝试将观察者添加到 swizzled 对象。它只是崩溃。

    0x00000000 in 0x00000000 () 0x0091d22a 在 _NSKeyValueRetainedObservationInfoForObject() 0x0092ec88 in -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] () 0x0092d6fd in -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] ()

这里是 swizzling 的实现

- (void)swizzleClass

    NSString *proxyClassName = [NSString stringWithFormat:@"MDSwizzled_%@", NSStringFromClass(self->isa)];
    Class proxyClass = NSClassFromString(proxyClassName);

    if (!proxyClass)
        proxyClass = [self createProxyClassWithName:proxyClassName];

    object_setClass(self, proxyClass);


- (Class)createProxyClassWithName:(NSString *)proxyClassName

    const char *c_proxyClassName = [proxyClassName cStringUsingEncoding:NSUTF8StringEncoding];
    Class proxyClass = objc_allocateClassPair(self->isa, c_proxyClassName, 0);

    Class dummyClass = [MDDummy class];
    class_addMethodFromClass(proxyClass, dummyClass, @selector(dealloc));
    class_addMethodFromClass(proxyClass, dummyClass, @selector(class));

    objc_registerClassPair(proxyClass);
    return proxyClass;

MDDummy 它只是一个方便的类持有方法(这和添加原始函数没有区别)。

@implementation MDDummy
- (void)dealloc


    //Special thinngs

    [super dealloc];


- (Class)class

    return //original class;

@end

编辑:

下面是class_addMethodFromClass函数的实现:

void class_addMethodFromClass(Class class, Class sourceClass, SEL selector)

    Method method = class_getInstanceMethod(sourceClass, selector);
    IMP methodImplementation = method_getImplementation(method);
    const char *types = method_getTypeEncoding(method);
    class_addMethod(class, selector, methodImplementation, types);

【问题讨论】:

你是在 swizzling 类之前还是之后将观察者添加到对象中? KVO is also implemented using the isa swizzling technique,所以 KVO 在你的 spivveries 之后停止工作也就不足为奇了 【参考方案1】:

你应该看看 Mike Ash 是如何处理这个问题的:https://github.com/mikeash/MAZeroingWeakRef

总结:以不同的方式处理 KVO 调配子类的调配——您必须修补 KVO 子类中的 KVO 方法...

【讨论】:

以上是关于我的 isa-swizzling 打破了 KVO的主要内容,如果未能解决你的问题,请参考以下文章

NotificationCenter KVC KVO Delegate总结

iOS底层探索之KVO—KVO原理分析

isa-swizzling 是什么鬼?

swift class type isa-swizzling

KVO - UIScrollView.contentSize误报?

KVO 更新 UITableViewCell