ios中遇到一些難解的問(wèn)題用swizz確實(shí)會(huì)比較方便的解決,比如批量換系統(tǒng)字體,比如AOP方式實(shí)現(xiàn)埋點(diǎn),比如想為AB都有一個(gè)共同的基類C的方法,但是又因C沒(méi)有公開(kāi)方法,此時(shí)想為AB新增一個(gè)方法fun1,或修改C中的某一個(gè)方法,此時(shí)swizz可以解決這個(gè)問(wèn)題。
要注意幾點(diǎn)
方法重復(fù),比如如果本來(lái)在其他的catalog分類中已經(jīng)有了一個(gè)方法fun1,此時(shí)想替換改類的fun2,這時(shí)候就容易出現(xiàn)混亂,導(dǎo)致無(wú)法預(yù)知執(zhí)行的是那個(gè)fun1
被實(shí)現(xiàn)的方法必須是當(dāng)前類方法,不能是父類方法,否則就不會(huì)執(zhí)行父類方法了
交換的方法如果用到了cmd(當(dāng)前方法的一個(gè)SEL指針),當(dāng)cmd發(fā)生了變化,就無(wú)法保證系統(tǒng)方法內(nèi)沒(méi)有使用到cmd
在+load方法中替換,難保證其他方法是否也在執(zhí)行,不會(huì)發(fā)生線程沖突導(dǎo)致失敗
文章完,大家自己可以做個(gè)試驗(yàn)看看效果吧
@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(@"已經(jīng)添加了 添加方法 class_replaceMethod %@",NSStringFromSelector(swizzledSelector));
class_replaceMethod(aClass,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
NSLog(@"沒(méi)有添加成功,交換方法 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