ios中遇到一些难解的问题用swizz确实会比较方便的解决,比如批量换系统字体,比如AOP方式实现埋点,比如想为AB都有一个共同的基类C的方法,但是又因C没有公开方法,此时想为AB新增一个方法fun1,或修改C中的某一个方法,此时swizz可以解决这个问题。
要注意几点
方法重复,比如如果本来在其他的catalog分类中已经有了一个方法fun1,此时想替换改类的fun2,这时候就容易出现混乱,导致无法预知执行的是那个fun1
被实现的方法必须是当前类方法,不能是父类方法,否则就不会执行父类方法了
交换的方法如果用到了cmd(当前方法的一个SEL指针),当cmd发生了变化,就无法保证系统方法内没有使用到cmd
在+load方法中替换,难保证其他方法是否也在执行,不会发生线程冲突导致失败
文章完,大家自己可以做个试验看看效果吧
@implementation ViewController(swizzz222)
-(void)xxx_viewDidLoad{
NSLog(@"xxx__222_viewDidLoad...");
[self xxx_viewDidLoad];
}
@end
@implementation ViewController(swizz)
-(void)xxx_viewDidLoad{
NSLog(@"xxx_viewDidLoad...");
[self xxx_viewDidLoad];
}
-(void)yyy_viewDidLoad{
NSLog(@"yyy_viewDidLoad...");
[self yyy_viewDidLoad];
}
@end
@implementation AppDelegate
+ (void)ht___replaceMethod:(Class)aClass originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector
{
Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector);
BOOL didAddMethod =
class_addMethod(aClass,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
NSLog(@"已经添加了 添加方法 class_replaceMethod %@",NSStringFromSelector(swizzledSelector));
class_replaceMethod(aClass,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
NSLog(@"没有添加成功,交换方法 method_exchangeImplementations %@",NSStringFromSelector(swizzledSelector));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// [self.class htv___replaceMethod:ViewController.class originalSelector:@selector(viewDidLoad) swizzledSelector:@selector(xxx_viewDidLoad)];
// [self.class htv___replaceMethod:ViewController.class originalSelector:@selector(viewDidLoad) swizzledSelector:@selector(yyy_viewDidLoad)];
[self.class htv___replaceMethod:ViewController.class originalSelector:@selector(viewDidAppear:) swizzledSelector:@selector(viewWillAppear:)];
return YES;
}
@end