Поймать селектор, используя class_addMethod для быстрых классов - PullRequest
0 голосов
/ 12 марта 2020

У меня есть Obj C класс:

@interface SomeClass : NSObject

@property(nonatomic, retain) NSNumber *sample;

@end

и

#import "SomeClass.h"
@import ObjectiveC;

@implementation SomeClass
@dynamic sample;

+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    NSLog(@"resolveInstanceMethod");
    if ([NSStringFromSelector(aSEL) hasPrefix:@"set"])
    {
        class_addMethod([self class], aSEL,
                        (IMP)setPropertyIMP, "v@:@");
    }
    else
    {
        class_addMethod([self class], aSEL,
                        (IMP)propertyIMP, "@@:");
    }
    return YES;
}

static id propertyIMP(id self, SEL _cmd)
{
    __block id value = nil;
    NSLog(@"propertyIMP");
    return value;
}

static void setPropertyIMP(id self, SEL _cmd, id aValue)
{
    NSLog(@"setPropertyIMP");
}

@end

и его дочерний элемент:

@objcMembers
class SomeClass1: SomeClass {
    dynamic var temp = NSNumber(1)

    override init() {
        let setterHasMethod = SomeClass1.resolveInstanceMethod(#selector(setter: SomeClass1.temp))
        let getterHasMethod = SomeClass1.resolveInstanceMethod(#selector(getter: SomeClass1.temp))
        print("setterHasMethod: \(setterHasMethod)")
        print("getterHasMethod: \(getterHasMethod)")
    }
}

Итак, когда я выполняю это

func doSome1() {
        let someInstance = SomeClass1()
        someInstance.temp = NSNumber(2)
        let res = someInstance.temp
        print("res: \(res)")
    }

propertyIMP и setPropertyIMP не вызываются.

, но для sample:

func doSome() {
        let someInstance = SomeClass1()
        someInstance.sample = NSNumber(2)
        let res = someInstance.sample
        print("res: \(res)")
    }

все работают правильно.

Is можно вызвать методы, используемые в class_addMethod для свойств Swift?

1 Ответ

0 голосов
/ 12 марта 2020

Вы должны использовать @NSManaged вместо dynamic:

@objcMembers
class SomeClass1: SomeClass {
    @NSManaged var temp = NSNumber(1)

    override init() {
        let setterHasMethod = SomeClass1.resolveInstanceMethod(#selector(setter: SomeClass1.temp))
        let getterHasMethod = SomeClass1.resolveInstanceMethod(#selector(getter: SomeClass1.temp))
        print("setterHasMethod: \(setterHasMethod)")
        print("getterHasMethod: \(getterHasMethod)")
    }
}
...