以下內容主要是學習《Effective Objective-C 2.0》所做的筆記,我所購買的原書為英文原版,由於自己英文水平有限,理解可能有疏漏
原書購買地址:亞馬遜
7、The System Frameworks
Item 47: Familiarize Yourself with the System Frameworks
要記住的:
(1)你有多種系統架構可以使用。其中最重要的兩個分別是Foundation和CoreFoundation,他們為多種應用提供了基本的架構庫。
(2)架構的存在主要是為了處理公用任務。比如音頻和視頻控制、網路以及資料管理等。
(3)記住純C寫的架構效能要優於Objective-C的架構,所以作為一名優秀的Objective-C開發人員需要瞭解很多C的核心機率。
Item 48: Prefer Block Enumeration to for Loops
一些知識點:
(1)
// Reverse fast enumerationNSArray *anArray = /* … */;for (id object in [anArray reverseObjectEnumerator]) { // Do something with `object’}
(2)
// Block enumerationNSArray *anArray = /* … */;[anArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop){ // Do something with `object’ if (shouldStop) { *stop = YES; }}];NSDictionary *aDictionary = /* … */;[aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, NSUInteger idx, BOOL *stop){ // Do something with `key’ and `object’ if (shouldStop) { *stop = YES; }}];NSSet *aSet = /* … */;[aSet enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop){ // Do something with `object’ if (shouldStop) { *stop = YES; }}];
(3)
// Casting in the block signatureNSDictionary *aDictionary = /* … */;[aDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *object, NSUInteger idx, BOOL *stop){ // Do something with `key’ and `object’}];
(4)
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id key, id obj, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
要記住的:
(1)枚舉集合有四種實現方式。最基本的方法是for迴圈,其次是使用NSEnumerator和快速枚舉。最新的且最高效的方法是使用塊枚舉方法。
(2)塊枚舉可以通過GCD在不添加任何額外代碼的情況下允許你使用枚舉同步.這是其他枚舉技術難以提供的。
(3)你可以將塊方法的參數類型修改為你確定的物件類型。
Item 49: Use Toll-Free Bridging for Collections with Custom Memory-Management Semantics
一些知識點:
(1)__bridge只做類型轉換,但是不修改對象記憶體管理權;
(2)__bridge_retained(也可以使用CFBridgingRetain)將Objective-C的對象轉換為Core Foundation的對象,同時將對象記憶體的管理權交給使用者,後續需要使用CFRelease或者相關方法來釋放對象;
(3)__bridge_transfer(也可以使用CFBridgingRelease)將Core Foundation的對象轉換為Objective-C的對象,同時將對象記憶體的管理權交給ARC,後續不需要使用CFRelease或者相關方法來釋放對象;
要記住的:
(1)自由橋接允許你將Objective-C對象和CF的純C對象互相轉換。
(2)使用CoreFoundation建立對象允許你在定義返回內容時自訂各種回呼函數。通過這種自由橋接可以讓你將CF對象交給Objective-C對象並使用正常的記憶體管理語義。
Item 50: Use NSCache Instead of NSDictionary for Caches
一些知識點:
(1)
// Using NSPurgeableData- (void)downloadDataForURL:(NSURL*)url { NSPurgeableData *cachedData = [_cache objectForKey:url]; if (cachedData) { // Stop the data being purged [cacheData beginContentAccess]; [self useData:cachedData]; // Mark that the data may be purged again [cacheData endContentAccess]; } else { // Cache miss EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url]; [fetcher startWithCompletionHandler:^(NSData *data){ NSPurgeableData *purgeableData = [NSPurgeableData dataWithData:data]; [_cache setObject:purgeableData forKey:url cost:purgeableData.length]; // Don’t need to beginContentAccess as it begins with access already marked [self useData:data]; // Mark that the data may be purged now [purgeableData endContentAccess]; }]; }}
要記住的:
(1)當使用NSDictionary儲存緩衝時考慮使用NSCache代替。NSCache與字典不同的地方有:提供了最佳的清理行為、安全執行緒並且不會拷貝key鍵。
(2)為緩衝中的對象提供必要的最大個數和容量限制。但不要把這些指標當做硬限制,它們僅用於指導緩衝釋放策略。
(3)使用NSPurgeableDataObject Storage Service緩衝,因為它可以自動清理資料並在緩衝釋放後自動移除。
(4)正確使用緩衝可以使你的程式更加易於響應。緩衝僅用於那些難以擷取的資料,比如網路請求或者硬碟讀取。
Item 51: Keep initialize and load Implementations Lean
一些知識點:
(1)
// Lean initialize// EOCClass.h#import <Foundation/Foundation.h>@interface EOCClass : NSObject@end// EOCClass.m#import "EOCClass.h"static const int kInterval = 10;static NSMutableArray *kSomeObjects;@implementation EOCClass+ (void)initialize { if (self == [EOCClass class]) { kSomeObjects = [NSMutableArray new]; }}@end
要記住的:
(1)如果一個類實現了load方法,那麼這個類在載入階段就會遍曆實現load方法。load方法也可以在類別中實現,但類中的實現總是先於類別中的實現執行。與其他方法不同的是,load方法不會覆蓋執行。
(2)在一個類第一次使用的時候,會執行initialize方法。這個方法會覆蓋執行,所以在執行時最好檢查是哪個類被初始化了。
(3)load和initialize方法都應該保持瘦實現,因為這兩個方法導致應用的響應以及停止都有可能導致內部循環參考。
(4)使用initialize方法來初始化不能在編譯時間初始化的全域變數。
Item 52: Remember that NSTimer Retains Its Target
一些知識點:
(1)
// Block support for NSTimer#import <Foundation/Foundation.h>@interface NSTimer (EOCBlocksSupport)+ (void)eoc_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)())block repeats:(BOOL)repeats;@end@implementation NSTimer (EOCBlocksSupport)+ (void)eoc_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)())block repeats:(BOOL)repeats{ return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(eoc_blockInvoke:) userInfo:[block copy] repeats:repeats];}+ (void)eoc_blockInvoke:(NSTimer*)timer { void (^block)() = timer.userInfo; if (block) { block(); }}@end
(2)
// No cycle using weak references- (void)startPolling { __weak EOCClass *weakSelf = self; _pollTimer = [NSTimer eoc_scheduledTimerWithTimeInterval:5.0 block:^{ EOCClass *strongSelf = weakSelf; [strongSelf p_doPoll]; } repeats:YES];}
要記住的:
(1)一個NSTimer對象在觸發時會保留目標直到計時器被顯式的設定無效。
(2)如果時間對象的目標保留了時間對象,那麼這個時間對象在執行時會很容易導致循環參考。這會被其他對象直接或非直接的觸發導致。
(3)使用塊方式可以使NSTimer對象實現打破這種循環參考的擴充。為了使這個塊實現作為NSTimer的公用介面一部分,可以把這個塊實現方法加到NSTimer的類擴充中。