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