Runtime 文集

一 方法调用的本质

1.runtime 的使用方法 ,首先导入objc/message.h ,在build setting 里面输入msg 设置为NO 因为从xcode5开始苹果不推荐使用底层的东西了擦!! runtime是运行时的机制,也就是说所有方法的调用在编译command+b的时候不会真正检测到底调用谁,只会在运行时候(动态)调用方法 ,方法调用的本质顺序; e.g.

[p eat] ---> [p performselector:@selector:eat] -> objc_msgsend(p,@selector:eat);
[Person eat] --> 先转化成类对象 Class personClass = [Person Class]; --> [personClass eat] --> [personClass performselector:@selector:eat]; ---> objc_msgsend([Person Class],@selector:eat);

无论是类调用放还是类对象调用方法本质都是 转化成objc_msgsend


- (void)text1 {
    
    person *p = [[person alloc] init];
    
    // xcode5 之后使用运行时方法
    
    // 苹果不推荐调用底层的方法
    // 在 buildsettings 搜索msg 设置为NO
    
    // 让p 发送消息
    objc_msgSend(p, @selector(eat));
    
    //
    objc_msgSend([person class], @selector(eat));  // 类对象
    
    // 类名调用类方法 其实就是用类对象调用方法
    [person eat];
    
    
    // 获取类对象
    
    Class personClass = [person class];
    [personClass performSelector:@selector(eat)];
    
    [personClass eat];

}


二 交换方法的实现

本质先得到两个方法 然后交换两个方法的实现请见官方文档

开发时候的作用很大比如更改文字的大小颜色等等替换官方的方法实现换成自己的但是记得回调官方的方法哦!! 这样可以替换所有的方法如果用分类的方法只能替换将来的已经使用的方法就没办法了一劳永逸!!! 装逼利器!

/** 
 * Sets the implementation of a method.
 * 
 * @param m The method for which to set an implementation.
 * @param imp The implemention to set to this method.
 * 
 * @return The previous implementation of the method.
 */
OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

/** 
 * Exchanges the implementations of two methods.
 * 
 * @param m1 Method to exchange with second method.
 * @param m2 Method to exchange with first method.
 * 
 * @note This is an atomic version of the following:
 *  \code 
 *  IMP imp1 = method_getImplementation(m1);
 *  IMP imp2 = method_getImplementation(m2);
 *  method_setImplementation(m1, imp2);
 *  method_setImplementation(m2, imp1);
 *  \endcode
 */
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);


#import "UIImage+myImage.h"
#import <objc/message.h>
@implementation UIImage (myImage)

+ (void)load {

      // 方法和属性等都是在类中所以用class_
    
    Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
    
    Method m2 = class_getClassMethod([UIImage class], @selector(stimageNamed:));
    
    method_exchangeImplementations(m1 , m2 );
}


+ (UIImage *)stimageNamed:(NSString *)imageName {
    UIImage *image = [UIImage stimageNamed:imageName];
    
    if (image ==nil) {
    
        NSLog(@"图片为nil");
    }
    
    return image;
    
    
}


三 动态的为某个类添加方法的实现

    class_addMethod(self , @selector(eat:), (IMP)eatsssss, "v@:@");
#import "person.h"
#import <objc/message.h>
@implementation person


// 调用了一个没有实现的方法就会调用这个方法 可以知道哪些方法没有实现  self _cmd //隐私参数

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
    // 动态添加方法
    if ([NSStringFromSelector(sel) isEqualToString:@"eat:"]) {
        
        /**
         
         cls: 给哪个类添加方法
         SEL:添加方法的方法编号
         IMP:函数名 方法实现  函数入口
         types : 方法类型
         
         */
        
        
        
        class_addMethod(self , @selector(eat:), (IMP)eatsssss, "v@:@");
    }

    return [super resolveInstanceMethod:sel];
}


// 定义函数
void eatsssss (id self ,SEL _cmd,id parames)
{
    NSLog(@"hahha%@",parames);

}


官方文档


Dynamic Method Resolution

There are situations where you might want to provide an implementation of a method dynamically. For example, the Objective-C declared properties feature (see Declared Properties in The Objective-C Programming Language) includes the @dynamic directive:

@dynamic propertyName;
which tells the compiler that the methods associated with the property will be provided dynamically.

You can implement the methods resolveInstanceMethod: and resolveClassMethod: to dynamically provide an implementation for a given selector for an instance and class method respectively.

An Objective-C method is simply a C function that take at least two arguments—self and _cmd. You can add a function to a class as a method using the function class_addMethod. Therefore, given the following function:

void dynamicMethodIMP(id self, SEL _cmd) {
    // implementation ....
}
you can dynamically add it to a class as a method (called resolveThisMethodDynamically) using resolveInstanceMethod: like this:

@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
          return YES;
    }
    return [super resolveInstanceMethod:aSEL];
}
@end
Forwarding methods (as described in Message Forwarding) and dynamic method resolution are, largely, orthogonal. A class has the opportunity to dynamically resolve a method before the forwarding mechanism kicks in. If respondsToSelector: or instancesRespondToSelector: is invoked, the dynamic method resolver is given the opportunity to provide an IMP for the selector first. If you implement resolveInstanceMethod: but want particular selectors to actually be forwarded via the forwarding mechanism, you return NO for those selectors.

Dynamic Loading

An Objective-C program can load and link new classes and categories while it’s running. The new code is incorporated into the program and treated identically to classes and categories loaded at the start.

Dynamic loading can be used to do a lot of different things. For example, the various modules in the System Preferences application are dynamically loaded.

In the Cocoa environment, dynamic loading is commonly used to allow applications to be customized. Others can write modules that your program loads at runtime—much as Interface Builder loads custom palettes and the OS X System Preferences application loads custom preference modules. The loadable modules extend what your application can do. They contribute to it in ways that you permit but could not have anticipated or defined yourself. You provide the framework, but others provide the code.

Although there is a runtime function that performs dynamic loading of Objective-C modules in Mach-O files (objc_loadModules, defined in objc/objc-load.h), Cocoa’s NSBundle class provides a significantly more convenient interface for dynamic loading—one that’s object-oriented and integrated with related services. See the NSBundle class specification in the Foundation framework reference for information on the NSBundle class and its use. See OS X ABI Mach-O File Format Reference for information on Mach-O files.

四 动态的为某个类添加属性

#import "NSObject+name.h"
#import <objc/message.h>
// @property在分类里面只会生成方法的set get方法的生明不会生成实现和_成员变量
@implementation NSObject (name)

- (void)setName:(NSString *)name {

    // 添加属性一般也给对象添加的 objc
    
    /***
     objc 给哪个对象添加属性
     
     key 属性名 根据key 去获取关联的对象  void * == id
     value 关联的值赋给的值name
     policy weak retain copy
     
     */
    objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_COPY);
    
}


- (NSString *)name {

    return objc_getAssociatedObject(self, @"name");
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容