二、對象、消息、runtime

6,理解 '屬性'這一概念

1, 可以用@property語法來定義對象中所封裝的數據

2, 通過'特質'來定義指定存儲數據所需的正確語義

原子性,

讀寫權限, 可以在分類中重新定義

內存管理語義, 注意,NSString ?Block ?應為 Copy

方法名

3, 在設置屬性所對應的實例變量時,一定要遵從該屬性所聲明的定義

4, 開發iOS程序時,應該使用nonatomic屬性, 因為atomic屬性會嚴重影響性能。

如果使用

@dynamic 代替@synthesize

編譯器不會這個屬性自動創建存取方法,和合并存取方法,并不會自動創建實例變量。如果用代碼訪問其中的屬性,編譯器也不會發出警示信息

例如

@property (nonatomic,assign) intabc;

@dynamic abc;

這樣,如果用戶就不會創建 _abc 這個實例變量了

7,在對象內部盡量直接訪問實例變量

1, 在對象內部讀取數據時,應該直接通過實例變量,而寫入數據時,應該通過屬性

2, 在初始化和delloc方法中,總是應該通過實例變量來讀寫數據

3,有時會使用惰性初始化技術配置某份數據,這種情況下,需要同過屬性來讀取數據

8,理解‘對象等同性’這一概念

1,若想檢測對象的等同性,請提供 ‘isEqual’與hash 方法

2, 相同的對象必須有相同的哈希碼,但是兩個哈希碼相同的對象未必相同

3,不用盲目的逐個檢測每條屬性,而是應該依照具體需求來指定檢測方案

4, 編寫hash方法時,應該使用技術速度快而且哈希碼碰撞幾率低的算法

9,以’類族‘隱藏實現細節

1, 類族模式可以把實現細節隱藏在一套簡單的公共接口后面

2, 系統框架中經常使用類族

3,從類族的公共抽象類中集成子類時需要當心,如果有開發文檔,則應首先閱讀

---> 類族,就是常說的,抽象類的靜態方法、類方法來創建實例對象

10,在既有類中使用關聯對象存放自定義數據 ( 動態添加屬性,相當于給一個對象中粘貼了一個對象,并設置了相關的內存管理寓意 )

1, 可以使用關聯對象機制來把兩個對象連起來

2, 定義關聯對象可指定內存管理語義,用以模仿定義屬性時采用的 擁有關系 與 非擁有關系

3, 只有在其他方法不可行時,才贏選用關聯對象,因為這種做法通常會引入難以查找的BUG

-- > 相當于給一個物件 粘上一個物件, 內存管理,應該尊重內存管理語義

引用

#import"objc/runtime.h"

全局

staticvoid*SceneTest4Key =@"SceneTest4Key";

-(void)test6

{

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Question"message:@"What do you want to do ?"delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Continue",nil];

void(^block)(NSInteger) = ^(NSIntegerbuttonIndex){

if(buttonIndex == 0) {

[self doCancel];

}else{

[self doContinue];

}

};

objc_setAssociatedObject(alert,SceneTest4Key, block,OBJC_ASSOCIATION_COPY);

[alert show];

}

-(void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

void(^block)(NSInteger) =objc_getAssociatedObject(alertView,SceneTest4Key);

block(buttonIndex);

}


11,理解 objc_msgSend 的作用

1, 消息由接受者、選擇子和參數構成。給某對象'發送消息'也就是相當于在該對象上調用方法

2,發給某對象的全部消息都要由 ‘動態消息派發系統’來處理,該系統會查處對應的方法,并執行代碼


12,理解消息轉發機制

1, 若對象無法相應某個選擇子,則進入消息轉發流程

2,通過運行期的動態方法解析功能,我們可以在需要用到某個方法時再將其加入到類中

3,對象可以把某個無法解讀的選擇子轉交給其他對象處理

4,經過上述兩步后,若是還是沒辦法處理選擇子,那就啟動完整的消息轉發機制


調用方法的流程

1,首先檢測對象的類有沒有實現這個方法,有就調用,沒有繼續往下

2,向上檢測父類有沒有實現,直到根類?NSObject,如果都沒有實現就繼續往下

3,進入轉發機制,以此往下

方案一:拯救1,檢測動態添加

1

+?(BOOL)resolveInstanceMethod:(SEL)sel

1

+?(BOOL)resolveClassMethod:(SEL)sel

方案二:拯救2,檢測消息是否轉發

1

-?(id)forwardingTargetForSelector:(SEL)aSelector

方案三:拯救3,檢測用戶是否已經注冊過,可以注冊但不實現

1

-?(NSMethodSignature?*)methodSignatureForSelector:(SEL)aSelector;

1

-?(void)forwardInvocation:(NSInvocation?*)anInvocation;


13,用‘方法調配技術’調試‘黑盒方法’

1, 在運行時,可以向類中新增和替換選擇子所對應的方法實現

2,使用另一份實現來替換原有的方法實現,這道工序叫做,‘方法調配’,開發者常用此技術向原有實現中添加功能

3,一般來說,只有調試程序的時候,才需要在運行時修改方法實現,這種做法不易濫用

動態的交換方法

示例:AFN 使用了動態交換方法,交換了網絡獲取的方法,在網絡獲取的時候來發送通知


NSString*abc =@"NSString";

NSLog(@"大寫%@", [abcuppercaseString]);

NSLog(@"小寫%@", [abclowercaseString]);

MethodoriginalMethod =class_getInstanceMethod([NSStringclass],@selector(lowercaseString));

MethodswappedMethod =class_getInstanceMethod([NSStringclass],@selector(uppercaseString));

method_exchangeImplementations(originalMethod, swappedMethod);

NSLog(@"大寫%@", [abcuppercaseString]);

NSLog(@"小寫%@", [abclowercaseString]);

2016-05-01 12:10:54.239 EasyIOSDemo[3214:283447]大寫NSSTRING

2016-05-01 12:10:54.240 EasyIOSDemo[3214:283447]小寫nsstring

2016-05-01 12:10:54.241 EasyIOSDemo[3214:283447]大寫nsstring

2016-05-01 12:10:54.241 EasyIOSDemo[3214:283447]小寫NSSTRING

14,理解‘類對象’的用意

1, 每一個實例都有一個指向Class 對象的指針,用以表明其類型,而這些Class對象 則構成了類的繼承體系。 這個指針是 isa,對象指向類,類指向父類,直至NSObject

和swift 存在差別,swift中的 isa 始終指向所屬的類

2,如果對象類型無法在編譯期確定,那么就應該使用類型信息查詢方法類探知

3,盡量使用類型信息查詢方法類確定對象類型,而不要使用直接比較類對象,因為某些對象可能實現了消息轉發功能

NSMutableDictionary*dic = [NSMutableDictionarynew];

[dic isMemberOfClass:[NSDictionaryclass]];// NO

[dicisMemberOfClass:[NSMutableDictionaryclass]];// YES

[dic isKindOfClass:[NSDictionaryclass]];// YES

[dic isKindOfClass:[NSArrayclass]];// NO;

isMemberOfClass ?判斷對象是否是某個類的實例

isKindOfClass 盤對想想是否是某個類活其派生類的實例

----- > 類對象,[NSArrayclass]

NSMutableDictionary*dic = [NSMutableDictionarynew];

NSLog(@"%@, %@", [dicclass], [NSMutableDictionaryclass]);

NSDictionary*dic1 = [NSDictionarynew];

NSLog(@"%@, %@", [dic1class], [NSDictionaryclass]);

__NSDictionaryM, NSMutableDictionary

__NSDictionary0, NSDictionary

在AppDelegate中打印

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

顯示 [2146:51427] AppDelegate, UIResponder

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容