6,理解 '屬性'這一概念
1赢笨, 可以用@property語(yǔ)法來(lái)定義對(duì)象中所封裝的數(shù)據(jù)未蝌。
2, 通過'特質(zhì)'來(lái)定義指定存儲(chǔ)數(shù)據(jù)所需的正確語(yǔ)義
原子性,
讀寫權(quán)限茧妒, 可以在分類中重新定義
內(nèi)存管理語(yǔ)義萧吠, 注意,NSString ?Block ?應(yīng)為 Copy
方法名
3桐筏, 在設(shè)置屬性所對(duì)應(yīng)的實(shí)例變量時(shí)纸型,一定要遵從該屬性所聲明的定義
4, 開發(fā)iOS程序時(shí)梅忌,應(yīng)該使用nonatomic屬性狰腌, 因?yàn)閍tomic屬性會(huì)嚴(yán)重影響性能。
如果使用
@dynamic 代替@synthesize
編譯器不會(huì)這個(gè)屬性自動(dòng)創(chuàng)建存取方法牧氮,和合并存取方法琼腔,并不會(huì)自動(dòng)創(chuàng)建實(shí)例變量。如果用代碼訪問其中的屬性踱葛,編譯器也不會(huì)發(fā)出警示信息
例如
@property (nonatomic,assign) intabc;
@dynamic abc;
這樣丹莲,如果用戶就不會(huì)創(chuàng)建 _abc 這個(gè)實(shí)例變量了
7,在對(duì)象內(nèi)部盡量直接訪問實(shí)例變量
1剖毯, 在對(duì)象內(nèi)部讀取數(shù)據(jù)時(shí)圾笨,應(yīng)該直接通過實(shí)例變量,而寫入數(shù)據(jù)時(shí)逊谋,應(yīng)該通過屬性
2擂达, 在初始化和delloc方法中,總是應(yīng)該通過實(shí)例變量來(lái)讀寫數(shù)據(jù)
3胶滋,有時(shí)會(huì)使用惰性初始化技術(shù)配置某份數(shù)據(jù)板鬓,這種情況下,需要同過屬性來(lái)讀取數(shù)據(jù)
8究恤,理解‘對(duì)象等同性’這一概念
1俭令,若想檢測(cè)對(duì)象的等同性,請(qǐng)?zhí)峁?‘isEqual’與hash 方法
2部宿, 相同的對(duì)象必須有相同的哈希碼抄腔,但是兩個(gè)哈希碼相同的對(duì)象未必相同
3瓢湃,不用盲目的逐個(gè)檢測(cè)每條屬性,而是應(yīng)該依照具體需求來(lái)指定檢測(cè)方案
4赫蛇, 編寫hash方法時(shí)绵患,應(yīng)該使用技術(shù)速度快而且哈希碼碰撞幾率低的算法
9,以’類族‘隱藏實(shí)現(xiàn)細(xì)節(jié)
1悟耘, 類族模式可以把實(shí)現(xiàn)細(xì)節(jié)隱藏在一套簡(jiǎn)單的公共接口后面
2落蝙, 系統(tǒng)框架中經(jīng)常使用類族
3,從類族的公共抽象類中集成子類時(shí)需要當(dāng)心暂幼,如果有開發(fā)文檔筏勒,則應(yīng)首先閱讀
---> 類族,就是常說的旺嬉,抽象類的靜態(tài)方法管行、類方法來(lái)創(chuàng)建實(shí)例對(duì)象
10,在既有類中使用關(guān)聯(lián)對(duì)象存放自定義數(shù)據(jù) ( 動(dòng)態(tài)添加屬性邪媳,相當(dāng)于給一個(gè)對(duì)象中粘貼了一個(gè)對(duì)象病瞳,并設(shè)置了相關(guān)的內(nèi)存管理寓意 )
1, 可以使用關(guān)聯(lián)對(duì)象機(jī)制來(lái)把兩個(gè)對(duì)象連起來(lái)
2悲酷, 定義關(guān)聯(lián)對(duì)象可指定內(nèi)存管理語(yǔ)義,用以模仿定義屬性時(shí)采用的 擁有關(guān)系 與 非擁有關(guān)系
3亲善, 只有在其他方法不可行時(shí)设易,才贏選用關(guān)聯(lián)對(duì)象,因?yàn)檫@種做法通常會(huì)引入難以查找的BUG
-- > 相當(dāng)于給一個(gè)物件 粘上一個(gè)物件蛹头, 內(nèi)存管理顿肺,應(yīng)該尊重內(nèi)存管理語(yǔ)義
引用
#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渣蜗, 消息由接受者屠尊、選擇子和參數(shù)構(gòu)成。給某對(duì)象'發(fā)送消息'也就是相當(dāng)于在該對(duì)象上調(diào)用方法
2耕拷,發(fā)給某對(duì)象的全部消息都要由 ‘動(dòng)態(tài)消息派發(fā)系統(tǒng)’來(lái)處理讼昆,該系統(tǒng)會(huì)查處對(duì)應(yīng)的方法,并執(zhí)行代碼
12骚烧,理解消息轉(zhuǎn)發(fā)機(jī)制
1浸赫, 若對(duì)象無(wú)法相應(yīng)某個(gè)選擇子,則進(jìn)入消息轉(zhuǎn)發(fā)流程
2赃绊,通過運(yùn)行期的動(dòng)態(tài)方法解析功能既峡,我們可以在需要用到某個(gè)方法時(shí)再將其加入到類中
3,對(duì)象可以把某個(gè)無(wú)法解讀的選擇子轉(zhuǎn)交給其他對(duì)象處理
4碧查,經(jīng)過上述兩步后运敢,若是還是沒辦法處理選擇子,那就啟動(dòng)完整的消息轉(zhuǎn)發(fā)機(jī)制
調(diào)用方法的流程
1,首先檢測(cè)對(duì)象的類有沒有實(shí)現(xiàn)這個(gè)方法传惠,有就調(diào)用迄沫,沒有繼續(xù)往下
2,向上檢測(cè)父類有沒有實(shí)現(xiàn)涉枫,直到根類?NSObject邢滑,如果都沒有實(shí)現(xiàn)就繼續(xù)往下
3,進(jìn)入轉(zhuǎn)發(fā)機(jī)制愿汰,以此往下
方案一:拯救1困后,檢測(cè)動(dòng)態(tài)添加
1
+?(BOOL)resolveInstanceMethod:(SEL)sel
1
+?(BOOL)resolveClassMethod:(SEL)sel
方案二:拯救2,檢測(cè)消息是否轉(zhuǎn)發(fā)
1
-?(id)forwardingTargetForSelector:(SEL)aSelector
方案三:拯救3衬廷,檢測(cè)用戶是否已經(jīng)注冊(cè)過摇予,可以注冊(cè)但不實(shí)現(xiàn)
1
-?(NSMethodSignature?*)methodSignatureForSelector:(SEL)aSelector;
1
-?(void)forwardInvocation:(NSInvocation?*)anInvocation;
13,用‘方法調(diào)配技術(shù)’調(diào)試‘黑盒方法’
1吗跋, 在運(yùn)行時(shí)侧戴,可以向類中新增和替換選擇子所對(duì)應(yīng)的方法實(shí)現(xiàn)
2,使用另一份實(shí)現(xiàn)來(lái)替換原有的方法實(shí)現(xiàn)跌宛,這道工序叫做酗宋,‘方法調(diào)配’,開發(fā)者常用此技術(shù)向原有實(shí)現(xiàn)中添加功能
3疆拘,一般來(lái)說蜕猫,只有調(diào)試程序的時(shí)候,才需要在運(yùn)行時(shí)修改方法實(shí)現(xiàn)哎迄,這種做法不易濫用
動(dòng)態(tài)的交換方法
示例:AFN 使用了動(dòng)態(tài)交換方法回右,交換了網(wǎng)絡(luò)獲取的方法,在網(wǎng)絡(luò)獲取的時(shí)候來(lái)發(fā)送通知
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漱挚,理解‘類對(duì)象’的用意
1翔烁, 每一個(gè)實(shí)例都有一個(gè)指向Class 對(duì)象的指針,用以表明其類型旨涝,而這些Class對(duì)象 則構(gòu)成了類的繼承體系蹬屹。 這個(gè)指針是 isa,對(duì)象指向類颊糜,類指向父類哩治,直至NSObject
和swift 存在差別,swift中的 isa 始終指向所屬的類
2衬鱼,如果對(duì)象類型無(wú)法在編譯期確定业筏,那么就應(yīng)該使用類型信息查詢方法類探知
3,盡量使用類型信息查詢方法類確定對(duì)象類型鸟赫,而不要使用直接比較類對(duì)象蒜胖,因?yàn)槟承?duì)象可能實(shí)現(xiàn)了消息轉(zhuǎn)發(fā)功能
NSMutableDictionary*dic = [NSMutableDictionarynew];
[dic isMemberOfClass:[NSDictionaryclass]];// NO
[dicisMemberOfClass:[NSMutableDictionaryclass]];// YES
[dic isKindOfClass:[NSDictionaryclass]];// YES
[dic isKindOfClass:[NSArrayclass]];// NO;
isMemberOfClass ?判斷對(duì)象是否是某個(gè)類的實(shí)例
isKindOfClass 盤對(duì)想想是否是某個(gè)類活其派生類的實(shí)例
----- > 類對(duì)象消别,[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