运行时的应用

2017-01-10  本文已影响0人  heigo

1、load和initialize的区别

+load和+initialize是 Objective-C runtime 会自动调用的两个类方法。但是它们被调用的时机却是有差别的,+load方法是在类被加载的时候调用的,而+initialize方法是在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。也就是说+initialize方法是以懒加载的方式被调用的,如果程序一直没有给某个类或它的子类发送消息,那么这个类的+initialize方法是永远不会被调用的。此外+load方法还有一个非常重要的特性,那就是子类、父类和分类中的+load方法的实现是被区别对待的。换句话说在 Objective-C runtime 自动调用+load方法时,分类中的+load方法并不会对主类中的+load方法造成覆盖。

2、使用运行时给程序添加功能

程序增加功能,而不是完全地替换某个功能,所以我们一般都需要在自定义的实现中调用原始的实现。

#import

+ (void)load {

staticdispatch_once_tonceToken;

dispatch_once(&onceToken, ^{

Class class = [selfclass];

SELoriginalSelector =@selector(viewWillAppear:);

SELswizzledSelector =@selector(mrc_viewWillAppear:);

MethodoriginalMethod =class_getInstanceMethod(class, originalSelector);

MethodswizzledMethod =class_getInstanceMethod(class, swizzledSelector);

BOOLsuccess =class_addMethod(class, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));

if(success) {

/*

主类本身有实现需要替换的方法,也就是class_addMethod方法返回NO。这种情况的处理比较简单,直接交换两个方法的实现就可以了:

*/

class_replaceMethod(class, swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));

}else{

method_exchangeImplementations(originalMethod, swizzledMethod);

/*主类本身没有实现需要替换的方法,而是继承了父类的实现,即class_addMethod方法返回YES。这时使用class_getInstanceMethod函数获取到的originalSelector指向的就是父类的方法,我们再通过执行class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));将父类的实现替换到我们自定义的mrc_viewWillAppear方法中。这样就达到了在mrc_viewWillAppear方法的实现中调用父类实现的目的。

*/

}

});

}

- (void)mrc_viewWillAppear:(BOOL)animated {

//先调用原始实现,由于主类本身有实现该方法,所以这里实际调用的是主类的实现

[selfmrc_viewWillAppear:animated];

//我们增加的功能

NSLog(@"sb王晨");

}

上一篇 下一篇

猜你喜欢

热点阅读