Runtime實(shí)戰(zhàn)

為了學(xué)習(xí)Runtime,我們應(yīng)該需要從幾個(gè)方面入手:

  1. 是什么?
  2. 為什么會(huì)出現(xiàn)?
  3. 怎么做?
  4. 分享
  5. 能干嘛?

是什么? 為什么會(huì)出現(xiàn)?

C語(yǔ)言是靜態(tài)語(yǔ)言,決定階段是在編譯期,而我們偉大的Apple工程師(其實(shí)Objective-C不是Apple發(fā)明的,這里姑且這么算吧)把Objective-C定義為了動(dòng)態(tài)語(yǔ)言。那要讓Objectiive-C具有動(dòng)態(tài)語(yǔ)言的特性,就必須有一個(gè)東西承載這種特性,而這種特性就是Runtime。個(gè)人理解,如有偏頗見(jiàn)諒!
具體其他定義可Google搜索,會(huì)看到有很多資料,不多說(shuō)了。

怎么做?

在Objective-C中一個(gè)類(lèi)其實(shí)主要分幾個(gè)部分:

  • protocol
  • Ivar
  • property
  • method

今天我們就來(lái)研究一下這主要的幾個(gè)部分。

先上一個(gè)隨便寫(xiě)的類(lèi):

#import <Foundation/Foundation.h>

@protocol RuntimeBaseProtocol <NSObject>

@optional
- (void)doBaseAction;

@end

@protocol RuntimeProtocol <NSObject>

@required
- (void)doRequiredAction;

@optional
- (void)doOptionalAction;

@end

@interface RuntimeObject : NSObject <RuntimeProtocol,RuntimeBaseProtocol>
{
    NSString *name;
    NSString *kind;
}
@property (nonatomic, strong) NSString *value;
@property (nonatomic, assign) int age;

+ (void)doClassMethod;
@end

簡(jiǎn)答解釋一下,我們定義了一個(gè)叫RuntimeObject的類(lèi),類(lèi)里面定義了一些東西:

  • 實(shí)現(xiàn)了RuntimeProtocol和RuntimeBaseProtocol協(xié)議
  • name、kind兩個(gè)實(shí)例變量
  • value、age兩個(gè)property
  • doClassMethod函數(shù)

接下來(lái)就是我們今天真正的主題,如何通過(guò)Runtime動(dòng)態(tài)性的獲取到這些東西?

其一,我們先Get下Protocol:

unsigned int count;
__unsafe_unretained Protocol **protocols = class_copyProtocolList([RuntimeObject class], &count);
for (unsigned int i = 0; i < count; i++) {
      const char *name = protocol_getName(protocols[i]);
      printf("%s\n",name);
}

我們發(fā)現(xiàn)真的準(zhǔn)確的輸出了呃!看:

RuntimeProtocol
RuntimeBaseProtocol
timg.jpeg

其二,我們?cè)賮?lái)試試Get下Property:

unsigned int count;
objc_property_t *propertys = class_copyPropertyList([RuntimeObject class], &count);
for (unsigned int i = 0; i < count; i++) {
        const char *name = property_getName(propertys[i]);
        printf("%s\n",name);
}

輸出如下:

value
age
hash
superclass
description
debugDescription

提示:hash、superclass、description、debugDescription是從NSObject來(lái)的

我們?cè)僖淮?/p>

timg.jpeg

接下來(lái)我們Get下Ivar、Method均告完美,哈哈哈?。。?/p>

分享

其實(shí)我們往上翻翻代碼不難看出,Runtime給我們提供了一組函數(shù),這些函數(shù)的形式主要為class_copyXXXX。這組函數(shù)就是用來(lái)獲取Ivar、Method、Property、Protocol的,他們分別是:

  • class_copyIvarList
  • class_copyPropertyList
  • class_copyProtocolList
  • class_copyMethodList

能干嘛?

如果你看到了這些,首先我先感謝你的支持!?? 但是我們還是得要討論下能用來(lái)干嘛呢?有什么鳥(niǎo)用?上面所有的代碼都是在我自己寫(xiě)的class基礎(chǔ)之上測(cè)試的,我都已經(jīng)有我寫(xiě)的代碼,何必多此一舉去獲取Method、Property等等吶?

騷年,不急!我們假設(shè)哈,如果某天你的主管要求你把他手機(jī)上所有安裝過(guò)的手機(jī)的Bundle ID提取出來(lái),然后用Excel表統(tǒng)計(jì)給他,你怎么搞?你是不是想拿榔頭砸他-去你Y的,什么JB玩意。但是騷年,我們不要忘記了,我們是coder??!我們難道就沒(méi)有辦法嗎?

直接上解決方法:

Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
            NSObject *workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
            NSLog(@"Installed apps:%@",[workspace performSelector:@selector(allApplications)]);
#pragma clang diagnostic pop

你調(diào)試一下就知道了,這段代碼可以提取到所有已經(jīng)安裝過(guò)的App列表,包含Bundle ID喔!它就是通過(guò)Runtime去獲取workspace類(lèi),然后performSelector函數(shù)!

后記

好了,Runtime先到這吧。其實(shí)它很簡(jiǎn)單,也就是Apple提供了一堆函數(shù)給你,然后讓你可以操作Ivar、Protocol、Property、Method,也就僅此而已!

附帶:

  • 一張截圖就截這么多吧,剩下的都一樣
Runtime_1.jpg
  • 通過(guò)Class獲取鏈接庫(kù)名稱(chēng)
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
const char *name = class_getImageName(LSApplicationWorkspace_class);
printf("%s\n",name);

落幕

所有測(cè)試代碼如下簡(jiǎn)書(shū)也不能上傳附件,不上GitHub了,太簡(jiǎn)單了

        { // Ivar
            unsigned int count;
            Ivar *ivars = class_copyIvarList([RuntimeObject class], &count);
            for (unsigned int i = 0; i < count; i++) {
                Ivar ivar = ivars[i];
                const char *name = ivar_getName(ivar);
                printf("%s\n",name);
            }
        }
        printf("\n\n\n");
        { // property
            unsigned int count;
            objc_property_t *propertys = class_copyPropertyList([RuntimeObject class], &count);
            for (unsigned int i = 0; i < count; i++) {
                const char *name = property_getName(propertys[i]);
                printf("%s\n",name);
            }
        }
        printf("\n\n\n");
        { // protocol
            unsigned int count;
            __unsafe_unretained Protocol **protocols = class_copyProtocolList([RuntimeObject class], &count);
            for (unsigned int i = 0; i < count; i++) {
                const char *name = protocol_getName(protocols[i]);
                printf("%s\n",name);
            }
        }
        printf("\n\n\n");
        { // method
            unsigned int count;
            Method *methods = class_copyMethodList([RuntimeObject class], &count);
            for (unsigned int i = 0; i < count; i++) {
                SEL sel = method_getName(methods[i]);
                printf("%s\n",sel_getName(sel));
            }
        }
        printf("\n\n\n");
        { // Get dynamic framework name
            Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
            const char *name = class_getImageName(LSApplicationWorkspace_class);
            printf("%s\n",name);
        }
        printf("\n\n\n");
        { // Installed apps
            Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
            NSObject *workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
            NSLog(@"Installed apps:%@",[workspace performSelector:@selector(allApplications)]);
#pragma clang diagnostic pop
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,030評(píng)論 0 9
  • 我們常常會(huì)聽(tīng)說(shuō) Objective-C 是一門(mén)動(dòng)態(tài)語(yǔ)言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,319評(píng)論 0 7
  • 本文轉(zhuǎn)載自:http://southpeak.github.io/2014/10/25/objective-c-r...
    idiot_lin閱讀 1,014評(píng)論 0 4
  • Objective-C語(yǔ)言是一門(mén)動(dòng)態(tài)語(yǔ)言,他將很多靜態(tài)語(yǔ)言在編譯和鏈接時(shí)期做的事情放到了運(yùn)行時(shí)來(lái)處理。這種動(dòng)態(tài)語(yǔ)言...
    tigger丨閱讀 1,573評(píng)論 0 8
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,872評(píng)論 33 466

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