iOS中的Runtime

一.isa

isa的理解

  • 在arm64架構(gòu)之前, isa就是一個(gè)普通的指針,存儲(chǔ)著Class、Meta-Class對(duì)象的內(nèi)存地址
  • 從arm64架構(gòu)開始,對(duì)isa進(jìn)行了優(yōu)化,變成了一個(gè)共用體( union )結(jié)構(gòu),還使用位域來(lái)存儲(chǔ)更多的信息

使用64位(8個(gè)字節(jié))存儲(chǔ)了大量信息

源碼---右方數(shù)字表示占用的位數(shù)
union isa_ t
{
    Class cls;
    uintptr_ ,t bits;
    struct (
        uintptr_ t nonpointer          : 1;
        uintptr_t has_assoc:           : 1;
        uintptr_t has_cxX_ dtor        : 1;
        uintptr_t shiftcls             : 33;
        uintptr_t magic                : 6;
        uintptr_t weakly_referenced    : 1;
        uintptr_t deallocating         : 1;
        uintptr_t has_sidetable_ rc    : 1;
        uintptr_t extra_rc             : 19;
    );
};

注意:shiftcls保存著類對(duì)象的地址值,占用33bit

位運(yùn)算---設(shè)值與取值
取值用按位與& (0b0000 0001-取第八位數(shù)值)
設(shè)值用按位與&(0b1111 1110-設(shè)第八位為0) + 按位或|(0b0000 0001-設(shè)第八位為1):需要確保其他值不變贷洲,只修改想設(shè)置的值
(按位非 ~)

圖片.png

二.class結(jié)構(gòu)

圖片.png

圖片.png

圖片.png

cache緩存

圖片.png

Class內(nèi)部結(jié)構(gòu)中有個(gè)方法緩存( cache_t ) , 用散列表來(lái)緩存曾經(jīng)調(diào)用過(guò)的方法,可以提高方法的查找速度(空間換時(shí)間
圖片.png

SEL --函數(shù)(方法)名
imp --指向函數(shù)的指針(函數(shù)地址)

用下面一張圖大概概括class的結(jié)構(gòu)


2531642047642_.pic_hd.jpg

三.objc_msgSend 消息轉(zhuǎn)發(fā)

OC的方法調(diào)用:消息機(jī)制,給方法調(diào)用者發(fā)送消息
objc_msgsend的執(zhí)行流程可以分為3大階段
- 消息發(fā)送

圖片.png

- 動(dòng)態(tài)方法解析
兩個(gè)關(guān)鍵實(shí)現(xiàn)方法:+resolveInstanceMethod:/+resolveClassMethod:

圖片.png

在OC中調(diào)用某個(gè)方法缴啡,當(dāng)?shù)谝徊剑l(fā)送階段未找到此方法時(shí)瓷们,會(huì)進(jìn)入第二步---動(dòng)態(tài)方法解析

//動(dòng)態(tài)添加實(shí)例方法
- (void)other
{
    NSLog(@"%s",__ func__ );
}
+ ( BOOL)resolveInstanceMethod: (SEL )sel
{
        if(sel == @selector(test)) f
        // 獲取其他方法
        Method method = class_ getInstanceMethod(self, @selector(other));
        //動(dòng)態(tài)添加test方法的突現(xiàn)
        class_addMethod(self, sel,
            method_getImplementation(method) ,
            method_getTypeEncoding(method));
        //返回YES代表有幼戀添加方法
        return YES;
}
    return [super resolveInstanceMethod:sel];
}

- 消息轉(zhuǎn)發(fā)
當(dāng)方法調(diào)用的第一步业栅,與第二步都沒(méi)有調(diào)用成功的時(shí)候。會(huì)進(jìn)入第三步--消息轉(zhuǎn)發(fā)谬晕,執(zhí)行方法 forwardingTargetForSelector

//當(dāng)進(jìn)入第三步時(shí)碘裕,會(huì)調(diào)用 MJCat 的test方法
- (id)forwardingTargetForSelector: (SEL)aSelector{
       if (aSelector == @selector(test)) f
          return [[MJCat alloc] init];
       }
       return [super forwardingTargetForSelector :aSelector];
}
圖片.png

擴(kuò)展

提醒編譯器不要自動(dòng)生成setter和getter的實(shí)現(xiàn)、不要自動(dòng)生成成員變量
@dynamic age;

四.[ self class]與[super class]

一.[ self class]的底層實(shí)現(xiàn)

  • 1.objc_msgSend消息接收者仍然是子類對(duì)象
    所以super class與self class 本質(zhì)是一樣的
-(Class) class{
   return object_ getClass(self );
}
  • 2.從父類開始查找方法的實(shí)現(xiàn)

二.[self superclass]的底層實(shí)現(xiàn)
superclass方法的返回值固蚤,也是取決于消息接收(調(diào)用)者是誰(shuí)

- (Class) superclass //獲取調(diào)用者的父類
{
  return class_getSuperclass(object_getClass(self)); //獲取self對(duì)象的父類方法
}

因此 [self superclass]與[super superclass]的本質(zhì)一樣

同一個(gè)類中,下面兩個(gè)方法的打印結(jié)果是一樣的

NSLog(@"[self class] = %@", [self class]);
NSLog(@"'[ super class]= %@"[super class]);
NSLog (@"[ self superclass] = %@", [self superclass]) ;
NSLog (@"[ super superclass] = %@", [super superclass]) ;

五.isKindOfClass和isMemberOfClass

實(shí)例方法
-(BOOL)isKindOfClass:(Class)aClass;// 判斷左邊實(shí)例的類對(duì)象或其父類的類對(duì)象是否跟右邊類對(duì)象相等
-(BOOL)isMemberOfClass:(Class)aClass; // 判斷左邊實(shí)例的類對(duì)象是否跟右邊類對(duì)象相等

類方法
+(BOOL)isKindOfClass:(Class)aClass歹茶;//左邊類的類對(duì)象父類的類對(duì)象(即元類)是否跟右邊類對(duì)象相等
+(BOOL)isMemberOfClass:(Class)aClass;//左邊類的類對(duì)象(即元類)是否跟右邊類對(duì)象相等

六.面試題

一.講一下OC的消息機(jī)制

  1. OC中的方法調(diào)用其實(shí)都是轉(zhuǎn)成了objc msgSend函數(shù)的調(diào)用,給receiver (方法調(diào)用者)發(fā)送了一條消息 ( selector方法名)

2.objc_ msgSend底層有3大階段
消息發(fā)送(當(dāng)前類夕玩、父類中查找)、動(dòng)態(tài)方法解析惊豺、消息轉(zhuǎn)發(fā)

二.什么是Runtime燎孟?平時(shí)項(xiàng)目中有用到過(guò)嗎?
OC是一門動(dòng)態(tài)性比較強(qiáng)的編程語(yǔ)言,允許很多操作推遲到程序運(yùn)行時(shí)再進(jìn)行
OC的動(dòng)態(tài)性就是由Runtime來(lái)支撐和實(shí)現(xiàn)的, Runtime是一 套C語(yǔ)言的API ,封裝了很多動(dòng)態(tài)性相關(guān)的函數(shù)
使用:
1.類相關(guān): 利用關(guān)聯(lián)對(duì)象尸昧,給分類添加屬性(成員變量)
2.成員變量:遍歷類的所有成員變量(修改textfield的占位文字顏色(修改成員變量值)揩页、字典轉(zhuǎn)模型(YYmodel的核心)、自動(dòng)歸檔解檔)
3.方法相關(guān)
1.方法交換(hook(鉤子)方法烹俗,最常用的應(yīng)用是防止數(shù)組爆侣、字典等越界崩潰).
2.利用消息發(fā)送機(jī)制進(jìn)行非常規(guī)的方法調(diào)用 objc_msgSend

方法交換實(shí)例:

+ (void)swizzleInstanceMethod2:(SEL)originalSel with:(SEL)swizzledSel {
    Method originalMethod = class_getInstanceMethod(self, originalSel);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSel);

    NSLog(@"給當(dāng)前分類添加原類的方法originalSelector");
    BOOL didAddMethod =
    class_addMethod(self,
                    originalSel,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        NSLog(@"originalSelector方法在原類中不存在,已經(jīng)添加成功幢妄,用下面的方法替換其實(shí)現(xiàn)");
        class_replaceMethod(self,
                            swizzledSel,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        NSLog(@"如果原類中已存在originalSelector的話兔仰,那么添加失敗而已,返回NO");
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

方法交換代碼解析
方法交換應(yīng)用場(chǎng)景//統(tǒng)計(jì)用戶進(jìn)入各個(gè)控制器的次數(shù)

  • Runtime中相關(guān)的API
//動(dòng)態(tài)創(chuàng)建-一個(gè)類(參數(shù):父類,類名,額外的內(nèi)存空間)
Class objc_allocateClassPair(Class superclass, const char *name, size_ _t extraBytes)
//注冊(cè)一個(gè)類(要在類注冊(cè)之前添加成員變量)
void objc_registerClassPair(Class cls)
//銷毀一個(gè)類
void objc_disposeClassPair(Class cls)
//獲取isa指向的Class
Class object_getClass(id obj)
//設(shè)置isa指向的Class
Class object_setClass(id obj, Class cls)
//判斷一個(gè)OC對(duì)象是否為Class
BOOL object_isClass(id obj)
//判斷一個(gè)Class是否為元類
BO0L class_isMetaClass(Class cls) 
//獲取父類
Class class_getSuperclass(Class cls)
  • Runtime中成員變量相關(guān)的API
//獲取一個(gè)實(shí)例變量
Ivar class_getInstanceVariable(Class cls, const char *name)

//拷貝實(shí)例變量列表(最后需要調(diào)用free釋放)
Ivar *Class_copyIvarList(Class cls, unsigned int *outCount)

//設(shè)置和獲取成員變量的值
void object_setIvar(id obj, Ivar ivar, id value)
id object_getIvar(id obj, Ivar ivar)

//動(dòng)態(tài)添加成員變量(已經(jīng)注冊(cè)的類是不能動(dòng)態(tài)添加成員變量的)
BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types)

//獲取成員變量的相關(guān)信息
const char *ivar_getName(Ivar v)
const char *ivar_getTypeEncoding(Ivar v)
  • Runtime中方法相關(guān)的API
//獲得一個(gè)實(shí)例方法蕉鸳、類方法
Method class_ getInstanceMethod(Class cls, SEL name)
Method class_ _getClassMethod(Class cls, SEL name)
//方法實(shí)現(xiàn)相關(guān)操作
IMP class_ getMethodImplementation(Class cls, SEL name)
IMP method_ set Imp lementation (Method m, IMP imp)
void method_ exchangeImp lementat ions (Method m1, Method m2)
//拷貝方法列表(最后需要凋用free釋放)
Method *Class_ copyMethodList(Class cls, unsigned int *outCount)
//動(dòng)態(tài)添加方法
B00L class_ addMethod(Class cls, SEL name, IMP imp, const char *types)
//動(dòng)態(tài)替換方法
IMP class_ replaceMethod(Class cls, SEL name, IMP imp, const char *types)
//獲取方法的相關(guān)信息(帯有copy的需要凋用free去釋放)
SEL method_ getName (Method m)
IMP method_ getImplementation(Method m)
const char *method_getTypeEncoding (Method m)
unsigned int method_getNumberOfArguments (Method m)
char *method_copyReturnType (Method m)
char *method_copyArgumentType(Method m, unsigned int index)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乎赴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子潮尝,更是在濱河造成了極大的恐慌榕吼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勉失,死亡現(xiàn)場(chǎng)離奇詭異羹蚣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乱凿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門度宦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)踢匣,“玉大人,你說(shuō)我怎么就攤上這事戈抄±牖#” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵划鸽,是天一觀的道長(zhǎng)输莺。 經(jīng)常有香客問(wèn)我,道長(zhǎng)裸诽,這世上最難降的妖魔是什么嫂用? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮丈冬,結(jié)果婚禮上嘱函,老公的妹妹穿的比我還像新娘。我一直安慰自己埂蕊,他們只是感情好往弓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蓄氧,像睡著了一般函似。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喉童,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天撇寞,我揣著相機(jī)與錄音,去河邊找鬼堂氯。 笑死蔑担,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咽白。 我是一名探鬼主播钟沛,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼局扶!你這毒婦竟也來(lái)了恨统?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤三妈,失蹤者是張志新(化名)和其女友劉穎畜埋,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畴蒲,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悠鞍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咖祭。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掩宜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出么翰,到底是詐尸還是另有隱情牺汤,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布浩嫌,位于F島的核電站檐迟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏码耐。R本人自食惡果不足惜追迟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骚腥。 院中可真熱鬧敦间,春花似錦、人聲如沸束铭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纯露。三九已至剿骨,卻和暖如春代芜,著一層夾襖步出監(jiān)牢的瞬間埠褪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工挤庇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钞速,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓嫡秕,卻偏偏與公主長(zhǎng)得像渴语,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昆咽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 該文章屬于劉小壯原創(chuàng)驾凶,轉(zhuǎn)載請(qǐng)注明:劉小壯[http://www.reibang.com/u/2de707c93d...
    劉小壯閱讀 6,902評(píng)論 2 15
  • 引導(dǎo) 對(duì)于從事 iOS 開發(fā)人員來(lái)說(shuō),所有的人都會(huì)答出「 Runtime 是運(yùn)行時(shí) 」掷酗,什么情況下用 Runtim...
    Winny_園球閱讀 4,207評(píng)論 3 75
  • 1.說(shuō)說(shuō)OC的消息機(jī)制? OC中的方法調(diào)用其實(shí)都是轉(zhuǎn)成了objc_msgSend函數(shù)的調(diào)用调违,給receiver(方...
    齊玉婷閱讀 454評(píng)論 0 0
  • Runtime消息傳遞: 一個(gè)對(duì)象的方法像這樣[obj foo],編譯器轉(zhuǎn)成消息發(fā)送objc_msgSend(ob...
    飛哥漂流記閱讀 225評(píng)論 0 0
  • 夜鶯2517閱讀 127,720評(píng)論 1 9