一、面向對象
1.1 一個NSObject對象佔用多少內存?
- 系統分配了16個字節給NSObject對象(通過malloc_size函數獲得)
- 但NSObject對象內部只使用了8個字節的空間(64bit環境下,可以通過class_getInstanceSize函數獲得)
1.2 對象的isa指針指向哪裏?
- instance對象的isa指向class對象
- class對象的isa指向meta-class對象
- meta-class對象的isa指向基類的meta-class對象
1.3 OC的類信息存放在哪裏?
- 對象方法、屬性、成員變量、協議信息,存放在class對象中 - 類方法,存放在meta-class對象中
- 成員變量的具體值,存放在instance對象
二、KVO
2.1 iOS用什麼方式實現對一個對象的KVO?(KVO的本質是什麼?)
- 利用RuntimeAPI動態生成一個子類,並且讓instance對象的isa指向這個全新的子類
- 當修改instance對象的屬性時,會調用Foundation的_NSSetXXXValueAndNotify函數
- willChangeValueForKey:
- 父類原來的setter
- didChangeValueForKey:
- 內部會觸發監聽器(Oberser)的監聽方法( observeValueForKeyPath:ofObject:change:context:)
2.2 如何手動觸發KVO?
- 手動調用willChangeValueForKey:和didChangeValueForKey:
2.3 直接修改成員變量會觸發KVO麼?
- 不會觸發KVO
三、KVC
3.1 通過KVC修改屬性會觸發KVO麼?
- 會觸發KVO
3.2 KVC的賦值和取值過程是怎樣的?原理是什麼?
四、Category
4.1 Category的使用場合是什麼?
4.2 Category的實現原理
- Category編譯之後的底層結構是struct category_t,裏面存儲着分類的對象方法、類方法、屬性、協議信息
- 在程序運行的時候,runtime會將Category的數據,合併到類信息中(類對象、元類對象中)
4.3 包含分類的類中的方法列表順序
- 方法列表順序
- 編譯文件靠後的分類的方法先導入方法列表
- 最後把當前類的方法導入方法列表
- 比如
- MJPerson+Eat.h中有run, eat兩個對象方法
- MJPerson+Test.h中有run, test兩個對象方法
- MJPerson.h中有run一個對象方法
- 編譯順序如下
- MJPerson+Eat.m
- MJPerson.m
- MJPerson+Test.m
- 那麼MJPerson類對象的方法列表爲
- MJPerson+Test的run, test方法
- MJPerson+Eat的run, eat方法
- MJPerson的run方法
- 查看文件的編譯順序
- 修改文件編譯順序
4.3 Category和Class Extension的區別是什麼?
- Class Extension在編譯的時候,它的數據就已經包含在類信息中
- Category是在運行時,纔會將數據合併到類信息中
4.4 Category中有load方法嗎?load方法是什麼時候調用的?load 方法能繼承嗎?
- 有load方法
- load方法在runtime加載類、分類的時候調用
- load方法可以繼承,但是一般情況下不會主動去調用load方法,都是讓系統自動調用
4.5 load、initialize方法的區別什麼?它們在category中的調用的順序?以及出現繼承時他們之間的調用過程?
4.6 Category能否添加成員變量?如果可以,如何給Category添加成員變量?
- 不能直接給Category添加成員變量,但是可以間接實現Category有成員變量的效果