倒計時回家還剩下兩天
1.在OC中如果有多個線程想使用同一份代碼,那么多線程讀寫可能會出現問題。這時候需要對某一個對象進行加鎖操作。@synchronized可以實現這種加鎖,但是效率非常低,同樣的NSLock與NSRecurisiveLock也是可以實現這種加鎖操作,但是效率不高。一種比較推崇的是GCD。下面是具體的實現代碼
_syncQueue = dispatch_get_global_create("DISPATCH_QUEUE_PRIORITY_DEFAULT",NULL);
-(NSString*) someString {
__block NSString* localSomething;
dispatch_sync(_syncQueue,^{
localSomeString = _someString;
});
return localSomeString
}
-(void) setSomeString:(NSString*) someString{
dispatch_barrier_async(_syncQueue,^{
_someString = someString;
});
}
2.盡量少用performSeletor,因為這個方法可以添加的方法參數有限。而且performseletor再ARC環境下,內存管理方面有缺失。因此如果想使用這種動態綁定方法,可以選擇使用NSInvocation,自己封裝一個對象跟調用方法,然后進行消息轉發。如果想延遲幾秒調用一個函數注意下面的寫法:
不推薦:
[self performSelector:@selector(show) withObject:nil afterDelay:0.4];
推薦:
dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW,(int64_t)(0.4*NSEC_PER_SEC));
dispatch_after(time,dispatch_get_main_quene(),^(){[self show] });
如果想吧任務放在主線程上面,也可以選擇下面兩種方法:
不推薦: [self performSelectorOnMianThread:@selector(doSomething) withObject:nil waitUntilDone:No];
推薦:
dispatch_async(dispatch_get_main_quene(),^({self doSemthing}));
3.很少有其他技術能與gcd的同步機制相媲美。對于那些只需要執行一次的代碼來說,也是如此,使用gcd的dispatch_once最為方便。然而在執行后臺任務時候,gcd并不一定是最佳方式。還有一種技術叫做NSOpertationQueue,它雖然與gcd不同,但是卻與之相關,開發者可以把操作以NSOpertation子類的形式放到隊列中,這些操作也能夠并發執行。
在兩者差別中,首先要注意:gcd是純c的API,而操作隊列是OC對象。gcd處理輕量級block而操作隊列處理重量級OC對象。
用NSOperationQueue類的addOperatonWithBlock方法搭配NSBlockOperation類來操作隊列,其語法與純gcd方法非常類似。使用NSOperation和NSOpertaionQueue的好處如下:
● 取消某個操作
● 指定操作間的依賴關系
● 通過鍵值觀測機制監控NSOperation屬性。
● 指定操作的優先級
● 重用NSOperation對象。
操作隊列很多地方勝過派發隊列。操作隊列提供了很多執行任務的方法,而且都是寫好了,直接就能用。開發者不用再編寫復雜的調度器。
NSNotificationCenter使用了操作隊列
本節要點
● 在解決多線程與任務管理問題時,派發隊列并非唯一方案。
● 操作隊列提供了一套高層次的OC API。能實現純gcd所具備的絕大部分功能,而且還能完成一些更為復雜的操作,那些操作如果該用gcd來實現,則需要另外寫代碼。
4.簡單講了一下dispatch_group的用法,用來封裝一組操作。只有當這個組中所有的任務都執行完成之后會有一個通知,然后繼續做后面操作。
5.直接看代碼吧,通常是單例的實現。
+(id) sharedInstance{
static EOCClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{sharedInstance = [[self alloc]init];});
return sharedInstance;
}
6.不要使用dispatch_get_current_queue 原因如下:
- dispatch_get_current_queue 函數的行為通常與開發者的預期不一致,這個函數已經廢棄了,只做調試用。
- 這個函數通常用來解決不可重入的代碼所引發的死鎖,然而如果可以用這個函數來解決的問題,通常也可以用特定的隊列來解決。
7.熟悉系統框架,并沒有講什么東西
8.只是作為一個建議,多用塊枚舉,少用for循環
9.上面提到過Foundation框架和CoreFoundation框架,Foundation中NSArray等collection,CoreFoundation中也有對應的CFArray,這兩種創建數組的方式也許有區別,然而“無縫橋接”技術可以使得這兩個類型之間平滑互轉。下面代碼演示了簡單的無縫橋接:
NSArray *anNSArray = @[@1,@2,@3,@4,@5];
CFArrayRef aCFArray = (__bridge CFArrayRef)anNSArray;
NSLog(@"size of array =%li",CFArrayGetCount(aCFArray));
__bridge本身的意思是:ARC仍然具備這個OC對象的所有權
10.構建緩存時選用NSCache而非NSDictionary
NSCache比NSDictonary好的地方是:當系統資源將要耗盡時,它可以自動刪減緩存(刪減“最近未使用的對象”)。下面這段代碼演示了緩存的用法:
#import <Foundation/Foundation.h>
//network fetcher class
typedef void(^EOCNetworkFetcherCompletionHandler)(NSData* data);
@interface EOCNetworkFetcher : NSObject
-(id)initWithURL(NSURL*)url;
-(void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandle)handler;
@end
// class that uses the network fetcher and caches results
@interface EOCClass :NSObject
@end
@implementation EOCClass{
NSCache* _cache;
}
-(id)init{
if(self = [super init]){
_cache = [NSCache new];
//cache a maximum of 100 URLs
_cache.countLimit = 100;
//the size in bytes of data is used as the cost,so this sets a cost limit of 5MB
_cache.totalCostLimit = 5*1024*1024;
}
return self;
}
-(void) downloadDataForUrl:(NSURL*)url{
NSData *cachedData = [_cache objectForKey:url];
if(cachedData){
//cached it
[self useData:cacheData];
}else{
//cache miss
EOCNetworkFetcher* fetcher = [[EOCNetworkFetcher alloc] initWithURL:url]
fetcher startWithCompletionHandler:^(NSData* data){
[_cache setObject:data forKey:url cost:data.length];
[self useData:data];
}];
}
}
@end
創建NSCache時,將其中可緩存的對象數目設定為100,將“總開銷”上限設為5MB