使用运行时替换字典的对象方法无效

Object method using runtime replacement dictionary is invalid

我尝试用运行时替换字典的 setObject:<#(nonnull id)#> forKey:<#(nonnull id<NSCopying>)#> 方法,但失败了。

代码:

#import "NSMutableDictionary+MD5MutableDictionary.h"
#import <objc/runtime.h>

@implementation NSMutableDictionary (MD5MutableDictionary)
+(void)load
{
    Method A = class_getInstanceMethod(self, @selector(setObject:forKey:));

    Method B = class_getInstanceMethod(self ,@selector(testsetObject:forKey:));

    method_exchangeImplementations(A, B);

}

- (void)testsetObject:(id)anObject forKey:(id<NSCopying>)aKey{
    [self testsetObject:anObject forKey:aKey];
    NSLog(@"success");
}

通过变量字典对象直接在外部调用例如:

NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:@"jack" forKey:@"name"];

如果你真的想实现你的目标,只需尝试下面的代码并处理私有 class __NSDictionaryM,它应该可以工作。

@implementation NSMutableDictionary (MD5MutableDictionary)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *className = @"__NSDictionaryM";
        Class class = NSClassFromString(className);

        SEL originalSelector = @selector(setObject:forKey:);
        SEL swizzledSelector = @selector(testsetObject:forKey:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (void)testsetObject:(id)anObject forKey:(id<NSCopying>)aKey{
    [self testsetObject:anObject forKey:aKey];
    NSLog(@"success");
}
@end