運(yùn)行時(shí)相關(guān)

  • 在CYPerson.h文件中
#import <Foundation/Foundation.h>


@interface CYPerson : NSObject
{
    int _money;
}
@property (nonatomic, assign, readonly) int age;
@property (nonatomic, assign) double height;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) NSArray *books;
@property (nonatomic, strong) id test;
@property (nonatomic, assign) CGRect rect;
@property (nonatomic, copy) void (^block)();
@property (nonatomic, assign) int *p;
@property (nonatomic, strong) CYCat *cat;
@end
  • 在CYPerson.m中
#import "CYPerson.h"

@implementation CYPerson

@end
  • 在main.m文件中
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "CYPerson.h"

void getIvars()
{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([CYPerson class], &count);
    // class_copyIvarList獲取成員變量列表,它返回的是一個(gè)指針指向的是最前面的那一個(gè)
    // ([CYPerson class], &count)這里面放的是類,你把類給我,我就獲取里面所有的成員變量。&count放的是成員變量的個(gè)數(shù)
    for (int i = 0; i < count; i++) {
        // for循環(huán)把所有成員變量遍歷出來(lái)
        Ivar ivar = ivars[i]; // *(ivars + i)
        // 取出每一個(gè)成員變量Ivar,而且Ivar是以數(shù)組的形式去訪問(wèn)
        // ivars[i]的寫法相當(dāng)于*(ivars + i)---跳到下一個(gè),取出這個(gè)指針指向的東西
        NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
       // %s是因?yàn)檫@里是C語(yǔ)言的東西
       // ivar_getName(ivar)這是去獲取所有成員變量的名字,這樣就挖掘到了所有成員變量
       // ivar_getTypeEncoding(ivar)表示獲取一個(gè)成員變量的類型字符串
       // 而且今后如果你有要獲取所有什么double,int類型的成員變量,這種方式,一打印就出來(lái)了
    }

    free(ivars);
    // 這里是通過(guò)copy出來(lái)的,所以需要釋放的
}

// 這里獲取所有屬性,和上面一樣
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        unsigned int count = 0;
        objc_property_t *properties = class_copyPropertyList([CYPerson class], &count);
        // class_copyPropertyList獲取屬性列表
        // class_copyProtocolList([CYPerson class], &count);是獲取協(xié)議列表,這樣可以獲取這個(gè)類遵循的所有協(xié)議
        // class_copyMethodList([CYPerson class], &count);是獲取方法列表,這樣可以知道這個(gè)類遵循 那些方法
        for (int i = 0; i < count; i++) {
            objc_property_t property = properties[i];
            NSLog(@"%s   ----     %s", property_getName(property), property_getAttributes(property));
       // property_getName(property)這是去獲取所有屬性的名字
       // property_getAttributes(property)獲取所有屬性的類型
        }

        free(properties);

//        method_exchangeImplementations(<#Method m1#>, <#Method m2#>)
//        方法交換---這個(gè)方法的意義在于我可以將蘋果系統(tǒng)內(nèi)部的方法替換成我自己的方法。當(dāng)你認(rèn)為系統(tǒng)自帶的方法不好用時(shí),你就將它替換為自己的方法
    }
    return 0;
}

*


*

*


*

*


*

  • 運(yùn)行時(shí)還可以動(dòng)態(tài)添加成員變量方法,動(dòng)態(tài)添加方法,動(dòng)態(tài)添加屬性,動(dòng)態(tài)添加協(xié)議這四個(gè)方法
  • 假如說(shuō)在代碼里面你只寫了如上幾個(gè)屬性,但是在我動(dòng)態(tài)添加后,在程序運(yùn)行過(guò)程中會(huì)無(wú)緣無(wú)故多一個(gè)屬性出來(lái),但是你在代碼中是看不見的。這就是運(yùn)行時(shí)能干的事情,相當(dāng)于操縱你的內(nèi)存,但是這也僅僅是運(yùn)行時(shí)的冰山一角

*


*

        method_exchangeImplementations(<#Method m1#>, <#Method m2#>)
//      方法交換---這個(gè)方法的意義在于我可以將蘋果系統(tǒng)內(nèi)部的方法替換成我自己的方法。當(dāng)你認(rèn)為系統(tǒng)自帶的方法不好用時(shí),你就將它替換為自己的方法





  • RunTime
    • 1.獲取內(nèi)部所有屬性和成員變量
    • 2.Method Swizzle--iOS黑魔法
      • 直觀用途:交換方法實(shí)現(xiàn)
  • 在CYPerson.h文件中
#import <Foundation/Foundation.h>

@interface CYPerson : NSObject
- (void)run;
- (void)study;
@end
  • 在CYPerson.m文件中
#import "CYPerson.h"
@implementation CYPerson

- (void)run
{
    NSLog(@"%s", __func__);
}

- (void)study
{
    NSLog(@"%s", __func__);
}

@end
#import "ViewController.h"
#import "CYPerson.h"
#import <objc/runtime.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

        Method method1 = class_getInstanceMethod([CYPerson class], @selector(run));
        Method method2 = class_getInstanceMethod([CYPerson class], @selector(study));
        method_exchangeImplementations(method1, method2);


        CYPerson *p = [[CYPerson alloc] init];
        [p run];

        [p study];
  • 可以看出來(lái):我調(diào)用run,它執(zhí)行的study。我調(diào)用study,它執(zhí)行的run

  • 那這個(gè)有啥用呢?
    • 在這里看出來(lái)是沒(méi)什么卵用,但是它的價(jià)值就在于可以交換系統(tǒng)自帶的方法
    • 比如說(shuō)我可以讓控制器的viewDidLoad方法換成我自己的viewDidLoad方法,讓它執(zhí)行的時(shí)候執(zhí)行到我自己的方法中去了。
    • 下面舉個(gè)例子:
      • 我想監(jiān)控控制器什么時(shí)候死亡,那我就得重寫dealloc方法。那么假如我們的項(xiàng)目中有30個(gè)或者更多的控制器,我想看它死掉沒(méi)有,防止循環(huán)引用,那我是不是20個(gè)都得實(shí)現(xiàn)dealloc方法?那我何不再搞一個(gè)方法出來(lái),比如說(shuō)CY_dealloc:方法。你本來(lái)想執(zhí)行dealloc的,現(xiàn)在執(zhí)行到我CY_dealloc:方法里去。那我就可以在這里統(tǒng)一監(jiān)控所有控制器的死亡
      • 下面我就做一下這個(gè)事情。為了保證所有控制器都有,我弄一個(gè)控制器的分類--UIViewController+CYExtention
#import <UIKit/UIKit.h>
#import <objc/runtime.h>

@implementation UIViewController (CYExtension)
+ (void)load
{
    Method method1 = class_getInstanceMethod(self, NSSelectorFromString(@"dealloc"));
    Method method2 = class_getInstanceMethod(self, @selector(CY_dealloc));
    method_exchangeImplementations(method1, method2);
}

- (void)CY_dealloc
{
    NSLog(@"%@ - CY_dealloc", self);
}
@end
  • 這樣就讓所有控制器的dealloc來(lái)到了我CY_dealloc里面,我可以統(tǒng)一監(jiān)控所有控制器
    • 上面我沒(méi)有導(dǎo)入頭文件,是因?yàn)閘oad方法是只要載入到內(nèi)存就會(huì)調(diào)一次,這個(gè)分類文件肯定是要裝入內(nèi)存的,所以頭文件要不要都無(wú)所謂,沒(méi)什么價(jià)值。但是你的導(dǎo)入#import <UIKit/UIKit.h>。因?yàn)槲业媚每刂破鞯拿?/li>
  • 我在Main.storyboard中弄多一些控制器會(huì)發(fā)現(xiàn):
  • 這樣的話,任何一個(gè)控制器掛了我都能監(jiān)控得到

  • 這里有一個(gè)小問(wèn)題:
    • 我在viewController.m文件中加上dealloc
- (void)dealloc
{
    NSLog(@"-------dealloc");
}
  • 然后讓上圖中的第二個(gè)控制器class為我們的viewController,運(yùn)行打印,會(huì)發(fā)現(xiàn)
  • 按理來(lái)說(shuō),一運(yùn)行點(diǎn)擊button后點(diǎn)擊返回是應(yīng)該調(diào)用dealloc方法,但是一調(diào)用它是應(yīng)該來(lái)到我們的CY_dealloc方法,應(yīng)該是只打印出CY_dealloc的,但是打印出來(lái)還是調(diào)用了dealloc方法。這是為什么呢?
    • 你會(huì)發(fā)現(xiàn),我們開始寫Method method1 = class_getInstanceMethod(self, NSSelectorFromString(@"dealloc"));的時(shí)候,開始如果寫的是@selector(@"dealloc"),這是禁止的,說(shuō)明這個(gè)方法ARC情況下是比較特殊的。但是前面@selector(run)和@selector(study)它們交換方法后,只打印了對(duì)方的方法,自己的方法就不會(huì)調(diào)用了。
    • 但是這里這么弄也正是我要說(shuō)的效果:用我們的方法交換系統(tǒng)的方法后還是想辦到系統(tǒng)的方法還是能調(diào)。因?yàn)槲覀冇袝r(shí)候是想在控制器死掉的時(shí)候做一些事情。比如說(shuō):在控制器死掉的時(shí)候清?掉一些東西,或者在控制器死掉的時(shí)候做一些請(qǐng)求:取消通知
- (void)dealloc
{
    NSLog(@"-------dealloc");

        self.data = nil;
        self.images = nil;

        [self cancel];
}
  • 但是如果按照開始的做法,我把dealloc換成CY_dealloc,就意味著我以后調(diào)dealloc只會(huì)來(lái)到CY_dealloc,以前系統(tǒng)的dealloc就沒(méi)法執(zhí)行。但是這里上面系統(tǒng)的dealloc可以執(zhí)行,但我告訴你如果換成了普通的方法它是不可能執(zhí)行的。就行前面我執(zhí)行run的時(shí)候它不可能執(zhí)行study,這兩個(gè)方法只會(huì)執(zhí)行它對(duì)應(yīng)的方法
  • 所以今后你如果做了方法的調(diào)換,不是系統(tǒng)的,我說(shuō)的是普通的方法換了。你如果調(diào)換后還想調(diào)回以前的方法,那就做一件事情執(zhí)行以下:(self.對(duì)應(yīng)的方法)。只有這樣它才會(huì)又調(diào)回自己以前的方法。因?yàn)槟氵@樣僅僅是做一個(gè)攔截嘛!就像下面:
- (void)CY_dealloc
{
    NSLog(@"%@ - CY_dealloc", self);

        [self CY_dealloc];
        //  這樣調(diào)用的是dealloc,又調(diào)回去了
}
  • 這里的意思:當(dāng)一個(gè)控制器死掉的時(shí)候,它肯定會(huì)調(diào)dealloc,但dealloc方法實(shí)現(xiàn)被我換掉了。所以它來(lái)到了CY_dealloc。執(zhí)行完- (void)CY_dealloc
    {
    NSLog(@"%@ - CY_dealloc", self);這段代碼,我再調(diào)用[self CY_dealloc];,它的方法實(shí)現(xiàn)是dealloc,所以又調(diào)回去了。所以今后你把系統(tǒng)方法換掉以后,我建議你再調(diào)回去,當(dāng)然有些特殊情況就特殊處理。
  • 那這個(gè)有什么價(jià)值呢?
    • 第一個(gè)以及體現(xiàn)了價(jià)值:攔截系統(tǒng)方法調(diào)用,我就可以在系統(tǒng)方法調(diào)用之前或者調(diào)用之后做一些事情
    • 第二個(gè)價(jià)值舉個(gè)例子:
      • 使用字典和數(shù)組的時(shí)候一直有一個(gè)頭疼的問(wèn)題:字典和數(shù)組賦值的時(shí)候不能為空,否則報(bào)錯(cuò): object cannot be nil'
    NSString *value = nil;

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    //    dict[@"name"] = value;

    NSMutableArray *array = [NSMutableArray array];
    [array addObject:value];
    array[0] = value;
  • 但是我們很多時(shí)候不知道別人給你傳的值是不是空啊!為了不報(bào)錯(cuò),我們經(jīng)常都得進(jìn)行判斷:如果value有值,我再執(zhí)行。
  • 那有沒(méi)有一個(gè)辦法可以過(guò)濾掉這些東西呢?只要發(fā)現(xiàn)傳進(jìn)來(lái)的值是個(gè)空的,我就不處理,那可不可以一勞永逸做到這點(diǎn)呢?我們只要寫下某一段代碼,以后凡是項(xiàng)目中傳空的值進(jìn)來(lái),它都不報(bào)錯(cuò)了,怎么去做呢?
    • 只要將NSMutable--的addObject:方法換掉,攔截這個(gè)方法,鴨蛋發(fā)現(xiàn)傳進(jìn)來(lái)的值是空的我就不調(diào),如果傳進(jìn)來(lái)的值不是nil,我就調(diào)回它以前的方法。那么這樣的話今后數(shù)組的訪問(wèn)或者字典的訪問(wèn)就不會(huì)存在傳進(jìn)來(lái)值為空?qǐng)?bào)錯(cuò)的問(wèn)題了
  • 還舉個(gè)例子:[UIImage imageName:我完全可以將imageName:方法攔截一下,我就可以對(duì)它傳進(jìn)來(lái)的圖片名進(jìn)行統(tǒng)一處理,比如說(shuō)什么夜間模式,什么皮膚,我就可以根據(jù)文件名去加載另外一個(gè)文件,統(tǒng)一攔截所有圖片

  • 但是還是不能亂換亂用,只是有些特殊功能可以做一下,亂用的話就不好了
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,748評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,165評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,595評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,435評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,943評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,175評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,713評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,599評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,788評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,034評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,408評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,747評(píng)論 2 370

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