1. 方法交换
+ (void)load {
Method originalMethod = class_getInstanceMethod(self, @selector(setText:));
Method customMethod = class_getInstanceMethod(self, @selector(customSetText:));
IMP originalImp = method_getImplementation(originalMethod);
IMP customImp = method_getImplementation(customMethod);
BOOL addResult = class_addMethod(self, @selector(setText:), customImp, "v@:@");
if (addResult) {
class_replaceMethod(self, @selector(customSetText:), originalImp, "v@:@");
} else {
method_exchangeImplementations(originalMethod, customMethod);
}
}
- (void)customSetText:(NSString *)text {
[self customSetText:text];
}
2. 动态添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(resolveThisMethodDynamically)) {
class_addMethod(self, sel, (IMP)dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
void dynamicMethodIMP(id self, SEL _cmd)
{
NSLog(@"%s", __func__);
}
3. 利用消息转发解决NSTimer循环引用(参考YYWeakProxy)
1. 核心代码
- (instancetype)initWithTarget:(id)target {
_target = target
return self
}
+ (instancetype)proxyWithTarget:(id)target {
return [[YYWeakProxy alloc] initWithTarget:target]
}
- (id)forwardingTargetForSelector:(SEL)selector {
return _target
}
2. 使用
_timer = [NSTimer timerWithTimeInterval:1 target:[YYWeakProxy proxyWithTarget:self] selector:@selector(timerAction) userInfo:nil repeats:YES];
[NSRunLoop.currentRunLoop addTimer:_timer forMode:NSRunLoopCommonModes];
[NSRunLoop.currentRunLoop run];
4. 获取类的所有属性,用于字典和模型映射
Class cls = [Person class];
do {
NSLog(@"class: %@", NSStringFromClass(cls));
unsigned int outCount = 0;
objc_property_t *propertyList = class_copyPropertyList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
NSString *name = @(property_getName(propertyList[i]));
NSLog(@"propertyName: %@", name);
}
cls = class_getSuperclass(cls);
} while (![ViewController isClassFromFoundation:cls]);
+ (BOOL)isClassFromFoundation:(Class)c
{
if (c == [NSObject class]) return YES;
static NSSet *foundationClasses;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
foundationClasses = [NSSet setWithObjects:
[NSURL class],
[NSDate class],
[NSValue class],
[NSData class],
[NSError class],
[NSArray class],
[NSDictionary class],
[NSString class],
[NSAttributedString class], nil];
});
__block BOOL result = NO;
[foundationClasses enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) {
if ([c isSubclassOfClass:foundationClass]) {
result = YES;
*stop = YES;
}
}];
return result;
}
未完待续。。。