Runtime基本介紹

Objective-C語言是一門動態(tài)語言,它將很多靜態(tài)語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態(tài)語言的優(yōu)勢在于:我們寫代碼時更具靈活性,如我們可以把消息轉(zhuǎn)發(fā)給我們想要的對象,或者隨意交換一個方法的實現(xiàn)等。

這種特性意味著Objective-C不僅需要一個編譯器,還需要一個運行時系統(tǒng)來執(zhí)行編譯的代碼。對于Objective-C來說,這個運行時系統(tǒng)就像一個操作系統(tǒng)一樣:它讓所有的工作可以正常的運行。這個運行時系統(tǒng)即Objc Runtime。Objc Runtime其實是一個Runtime庫,它基本上是用C和匯編寫的,這個庫使得C語言有了面向?qū)ο蟮哪芰Α?/p>

Runtime庫主要做下面幾件事:
封裝:在這個庫中,對象可以用C語言中的結(jié)構(gòu)體表示,而方法可以用C函數(shù)來實現(xiàn),另外再加上了一些額外的特性。這些結(jié)構(gòu)體和函數(shù)被runtime函數(shù)封裝后,我們就可以在程序運行時創(chuàng)建,檢查,修改類、對象和它們的方法了。

找出方法的最終執(zhí)行代碼:當程序執(zhí)行[object doSomething]時,會向消息接收者(object)發(fā)送一條消息(doSomething),runtime會根據(jù)消息接收者是否能響應該消息而做出不同的反應。

基本解釋

  • Runtime 是一套比較底層的純C語言API, 它是OC的幕后工作者
  • 我們平時寫的OC代碼在運行時都會編譯器轉(zhuǎn)為runtime的C語言代碼
  • 其中最主要的是消息機制OC的函數(shù)調(diào)用成為消息發(fā)送 屬于動態(tài)調(diào)用過程 在編譯的時候并不能決定真正調(diào)用哪個函數(shù)
  • 事實證明, 在編譯階段,OC可以調(diào)用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要申明過就不會報錯
  • 而C語言在編譯階段就會報錯 只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調(diào)用。

實際用法

#import "ViewController.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import "Person.h"
#import "NSObject+my.h"


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *phoneImg;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    /******************1.消息發(fā)送*******************/
    
    Person *p = [Person new];
//    [p run];
    objc_msgSend(p,@selector(run));
    
    objc_msgSend([Person class], @selector(run));

    /******************2.方法交換*******************/
    self.phoneImg.image = [UIImage imageNamed:@"banner"];
    
    /******************3.獲取實例變量*******************/
    
    //參數(shù)1:你要獲取的類,參數(shù)2:數(shù)量指針
    
    unsigned int iVarCount;
    
    Ivar *iVarList = class_copyIvarList([Person class], &iVarCount);
    
    for (int i = 0; i < iVarCount; i++) {
        
        Ivar aVar = iVarList[i];
        
        NSLog(@"%s",ivar_getName(aVar));
    }
    /******************4.獲取對象方法*******************/
    unsigned int methodCount;
    
    Method *methodList = class_copyMethodList([Person class], &methodCount);
    
    for (int i = 0; i < methodCount; i++) {
        
        Method aMethod = methodList[i];
        
        SEL methodSel = method_getName(aMethod);
        
        NSLog(@"%@",NSStringFromSelector(methodSel));

    }
    
    /******************5.動態(tài)創(chuàng)建類,添加實例變量*******************/
    
    //創(chuàng)建一個類 參數(shù)1:父類 參數(shù)2:你要創(chuàng)建的類名 參數(shù)3:
     Class MyClass = objc_allocateClassPair([Person class], "MyClass", 0);
    
    
    //添加實例變量  參數(shù)1:要往哪個類添加, 參數(shù)2:變量名 參數(shù)3:變量大小 參數(shù)4:對齊方式-傳0 參數(shù)5:類型編碼(要去文檔查看)
    
    
    if (class_addIvar(MyClass, "_city", sizeof(NSString *), 0, "@")) {
        NSLog(@"變量添加成功");
        
        
        id myP = [[MyClass alloc]init];//使用id類型來接收
        
        //賦值
        [myP setValue:@"廣州" forKey:@"_city"];
        
        //取出
        NSLog(@"%@",[myP valueForKey:@"_city"]);
        
    }
    
    /******************6.動態(tài)創(chuàng)建類,添加對象方法*******************/
    
    //添加對象方法  參數(shù)1:要往哪個類添加, 參數(shù)2:方法選擇器 參數(shù)3:實現(xiàn) 參數(shù)4:實現(xiàn)的函數(shù)類型編碼(要去文檔查看)
    
    if (class_addMethod(MyClass, @selector(aMethod:), (IMP)aMethod_IMP, "v@:@")) {
        
        NSLog(@"方法添加成功");
        
        id myP = [[MyClass alloc]init];//使用id類型來接收
        
        [myP aMethod:@"哈哈"];
        
        
    }
    
    /******************7.分類添加屬性*******************/
    
    NSObject *obj = [NSObject new];

    obj.myName = @"aNema";
    
    NSLog(@"%@",obj.myName);
    
    

}

//方法實現(xiàn)
void aMethod_IMP(id self,SEL _cmd,NSString * str){

    NSLog(@"%s = %@",__func__,str);

}

//OC里的方法
- (void)aMethod:(NSString *)str{
    
    NSLog(@"%s",__func__);
    
}


@end

UIImage分類

//
//  UIImage+my.m
//  01-runtime
//
//  Created by iOS on 15/12/24.
//  Copyright ? 2015年 iOS. All rights reserved.
//

#import "UIImage+my.h"
#import <objc/runtime.h>

@implementation UIImage (my)

+ (void)load{
    
    //1.獲取舊方法
    
    Method imageNameM = class_getClassMethod(self, @selector(imageNamed:));
    
    //2.獲取新方法
    Method imageWithNameM = class_getClassMethod(self, @selector(imageWithName:));
    
    //3.交換
    
    method_exchangeImplementations(imageNameM, imageWithNameM);
    
    
    
}


//+ (UIImage *)imageNamed:(NSString *)name{
//    
//}


+ (UIImage *)imageWithName:(NSString *)name{
    
    NSLog(@"%s",__func__);
    
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        
        name = [name stringByAppendingString:@"_iPad"];
        
    }else {
        name = [name stringByAppendingString:@"_iPhone"];
    }
    

    return [self imageWithName:name];
}

@end

NSObject分類

//
//  NSObject+my.m
//  01-runtime
//
//  Created by iOS on 15/12/24.
//  Copyright ? 2015年 iOS. All rights reserved.
//

#import "NSObject+my.h"
#import <objc/runtime.h>

@implementation NSObject (my)

static const void *myNameKey = "myNameKey";

- (void)setMyName:(NSString *)myName{
    
//    [self setValue:myName forKey:@"myName"];
    
    //設(shè)置關(guān)聯(lián)  參數(shù)1:要關(guān)聯(lián)的對象 參數(shù)2:綁定的key 參數(shù)3:這個key要關(guān)聯(lián)的值 參數(shù)4:要使用的策略
    objc_setAssociatedObject(self, myNameKey, myName, OBJC_ASSOCIATION_COPY_NONATOMIC);
    
}

- (NSString *)myName{
    
//    return [self valueForKey:@"myName"];
    return objc_getAssociatedObject(self, myNameKey);
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,893評論 33 466
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,074評論 0 9
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,249評論 0 9
  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,812評論 7 64
  • 本周我們的主題,繼續(xù)研究《孫子兵法》,《九變篇》曰:“是故智者之慮,必雜于利害。雜于利,而務可信也;雜于害,而患可...
    吾心自足閱讀 483評論 0 1

友情鏈接更多精彩內(nèi)容