前言
- 本章主要是描述如何簡單使用runtime,runtime蘋果官方是開源的,想要了解更多的朋友可以直接去看官方源碼.
一, runtime簡介
- runtime簡稱為運(yùn)行時,OC是運(yùn)行時機(jī)制,比如OC的消息機(jī)制.
- 關(guān)于C語言,我們都知道它是在編譯的時候就會決定去調(diào)用哪個函數(shù).
- 但是,OC是在編譯的時候并不能調(diào)用函數(shù),而是在運(yùn)行的時候才會真正的去根據(jù)函數(shù)名去找到并調(diào)用對應(yīng)的函數(shù)的方法.
- OC與C語言區(qū)別之一:OC是運(yùn)行時機(jī)制,C語言是編譯時機(jī)制.比如說:在OC中,只要你聲明了函數(shù),但是沒有去實(shí)現(xiàn)它,在編譯的時候是不會報錯的,只有在運(yùn)行的時候才會報錯.但是,C語言只要你沒有聲明函數(shù),如果直接去實(shí)現(xiàn)方法的話,它會在編譯的時候就會報錯.
二, runtime的作用
1, 發(fā)送消息
- 眾所周知, OC是消息機(jī)制,其本質(zhì)就是讓對象發(fā)送消息,計算機(jī)是無法讀取OC語言,其本質(zhì)是將OC語言通過runtime轉(zhuǎn)化為C語言,最后轉(zhuǎn)為二進(jìn)制.
- 使用runtime的前提是需要導(dǎo)入#import< objc/message.h>
或者是#imaport< objc/runtime.h > - 只有對象才能發(fā)送消息,在runtime中發(fā)送消息的方法是:objc_msgSend, runtime中的方法大多都是以objc開頭的.
三, runtime的使用場景
- 使用場景1 : runtime的消息機(jī)制,自己寫自己的框架
- 使用場景2 : 如果我們想要去調(diào)用別的框架或者是系統(tǒng)中沒有暴露出來的方法.
- 使用場景3 : 如果我們想要研究系統(tǒng)內(nèi)部有哪些私有方法, 有哪些私有屬性.
- 使用場景4 : 如果我們想要獲取到系統(tǒng)自帶的控件的子控件
- 實(shí)現(xiàn)原理 : 根據(jù)方法名去找對應(yīng)的方法實(shí)現(xiàn),具體例子如下:
// 新建一個學(xué)生類WGStudent, 在類中什么一個對象方法和類方法.
#import <Foundation/Foundation.h>
WGStudent.h文件
@interface WGStudent : NSObject
// - (void)study;
// + (void)eat;
@end
WGStudent.m文件
#import "WGStudent.h"
@implementation WGStudent
- (void)study {
NSLog(@"學(xué)習(xí)數(shù)學(xué)");
}
+ (void)eat {
NSLog(@"吃飯");
}
@end
- 注意 : 這里新建WGStudent類的目的主要是用于解釋類的調(diào)用原理
#import "ViewController.h"
#import "WGStudent.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 對象發(fā)送消息
// OC中調(diào)用對象方法
WGStudent *student = [[WGStudent alloc] init];
[student study];
// [student study]的本質(zhì)就是讓對象發(fā)送消息
objc_msgSend(student @selecter(study));
// 類調(diào)用對象方法,發(fā)送消息
// 調(diào)用類方法的方式:兩種
// 第一種通過類名調(diào)用
[student eat];
// 第二種通過類對象調(diào)用
[[student class] eat];
// 用類名調(diào)用類方法蹦漠,底層會自動把類名轉(zhuǎn)換成類對象調(diào)用
// 本質(zhì):讓類對象發(fā)送消息
objc_msgSend([student class], @selector(eat));
}
@end
- 特別注意 : 如果你這里就運(yùn)行程序,程序會直接報錯,所以這里需要做兩步操作.
- 1, 判斷是否導(dǎo)入#import< objc/message.h> 或者 #imaport< objc/runtime.h >
- 2, 進(jìn)入工程 -> Build Settting -> msg -> No(不嚴(yán)格檢測發(fā)送消息的調(diào)用)
四, 解析創(chuàng)建一個對象時,如何使用runtime轉(zhuǎn)化OC的.
// 解析創(chuàng)建對象過程
WGStudent *student = [[WGStudent alloc] init];
// 1, 分配存儲空間
WGStudent *student = [WGStudent alloc];
--> 使用runtime創(chuàng)建對象
objc_msgSend([WGStudent class], @selector(alloc));
// 2, 初始化
student = [student init];
--> 使用runtime進(jìn)行初始化
student = objc_msgSend(student, @selector(init));
// 3, 調(diào)用對象方法
[student study];
--> 使用runtime調(diào)用方法
objc_msgSend(student, @selector(study));
-
知識拓展 :
1, xcode6開始,蘋果不推薦我們使用runtime,把很多函數(shù)的參數(shù)注釋.
2, xcode6做了一些事情,導(dǎo)致不能調(diào)用objc_msgSend
注意點(diǎn):把函數(shù)名轉(zhuǎn)換成某個函數(shù)指針,一定要用括號包住,在調(diào)用
((NSObject * (*)(id, SEL))objc_msgSend)(self,@selector(eat));
objc_msgSend(self,@selector(eat));