Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
854 views
in Technique[技术] by (71.8m points)

objective c - My isa-swizzling breaks KVO

I'm trying to implement isa swizzling because I need some actions to happen in dealloc method of certain object. I'm overriding - (Class)class; method to return original class (as KVO does). Everything works fine, until I try to add observer to swizzled object. It just crashes.

  1. 0x00000000 in 0x00000000 ()
  2. 0x0091d22a in _NSKeyValueRetainedObservationInfoForObject ()
  3. 0x0092ec88 in -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] ()
  4. 0x0092d6fd in -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] ()

Here is implementation of 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 it's just a class holding method in convinietn way (there is no difference between this and adding raw functions).

@implementation MDDummy
- (void)dealloc
{

    //Special thinngs

    [super dealloc];
}

- (Class)class
{
    return //original class;
}
@end

EDIT:

Here's implementation of class_addMethodFromClass function:

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);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You should check out how Mike Ash handles this: https://github.com/mikeash/MAZeroingWeakRef

Summary: handle swizzling a KVO-swizzled subclass differently--you'll have to patch the KVO methods in the KVO subclass...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...