倒計(jì)時(shí)回家還剩下兩天
1.在OC中如果有多個(gè)線程想使用同一份代碼,那么多線程讀寫(xiě)可能會(huì)出現(xiàn)問(wèn)題。這時(shí)候需要對(duì)某一個(gè)對(duì)象進(jìn)行加鎖操作。@synchronized可以實(shí)現(xiàn)這種加鎖,但是效率非常低,同樣的NSLock與NSRecurisiveLock也是可以實(shí)現(xiàn)這種加鎖操作,但是效率不高。一種比較推崇的是GCD。下面是具體的實(shí)現(xiàn)代碼
_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,因?yàn)檫@個(gè)方法可以添加的方法參數(shù)有限。而且performseletor再ARC環(huán)境下,內(nèi)存管理方面有缺失。因此如果想使用這種動(dòng)態(tài)綁定方法,可以選擇使用NSInvocation,自己封裝一個(gè)對(duì)象跟調(diào)用方法,然后進(jìn)行消息轉(zhuǎn)發(fā)。如果想延遲幾秒調(diào)用一個(gè)函數(shù)注意下面的寫(xiě)法:
不推薦:
[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] });
如果想吧任務(wù)放在主線程上面,也可以選擇下面兩種方法:
不推薦: [self performSelectorOnMianThread:@selector(doSomething) withObject:nil waitUntilDone:No];
推薦:
dispatch_async(dispatch_get_main_quene(),^({self doSemthing}));
3.很少有其他技術(shù)能與gcd的同步機(jī)制相媲美。對(duì)于那些只需要執(zhí)行一次的代碼來(lái)說(shuō),也是如此,使用gcd的dispatch_once最為方便。然而在執(zhí)行后臺(tái)任務(wù)時(shí)候,gcd并不一定是最佳方式。還有一種技術(shù)叫做NSOpertationQueue,它雖然與gcd不同,但是卻與之相關(guān),開(kāi)發(fā)者可以把操作以NSOpertation子類的形式放到隊(duì)列中,這些操作也能夠并發(fā)執(zhí)行。
在兩者差別中,首先要注意:gcd是純c的API,而操作隊(duì)列是OC對(duì)象。gcd處理輕量級(jí)block而操作隊(duì)列處理重量級(jí)OC對(duì)象。
用NSOperationQueue類的addOperatonWithBlock方法搭配NSBlockOperation類來(lái)操作隊(duì)列,其語(yǔ)法與純gcd方法非常類似。使用NSOperation和NSOpertaionQueue的好處如下:
● 取消某個(gè)操作
● 指定操作間的依賴關(guān)系
● 通過(guò)鍵值觀測(cè)機(jī)制監(jiān)控NSOperation屬性。
● 指定操作的優(yōu)先級(jí)
● 重用NSOperation對(duì)象。
操作隊(duì)列很多地方勝過(guò)派發(fā)隊(duì)列。操作隊(duì)列提供了很多執(zhí)行任務(wù)的方法,而且都是寫(xiě)好了,直接就能用。開(kāi)發(fā)者不用再編寫(xiě)復(fù)雜的調(diào)度器。
NSNotificationCenter使用了操作隊(duì)列
本節(jié)要點(diǎn)
● 在解決多線程與任務(wù)管理問(wèn)題時(shí),派發(fā)隊(duì)列并非唯一方案。
● 操作隊(duì)列提供了一套高層次的OC API。能實(shí)現(xiàn)純gcd所具備的絕大部分功能,而且還能完成一些更為復(fù)雜的操作,那些操作如果該用gcd來(lái)實(shí)現(xiàn),則需要另外寫(xiě)代碼。
4.簡(jiǎn)單講了一下dispatch_group的用法,用來(lái)封裝一組操作。只有當(dāng)這個(gè)組中所有的任務(wù)都執(zhí)行完成之后會(huì)有一個(gè)通知,然后繼續(xù)做后面操作。
5.直接看代碼吧,通常是單例的實(shí)現(xiàn)。
+(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 函數(shù)的行為通常與開(kāi)發(fā)者的預(yù)期不一致,這個(gè)函數(shù)已經(jīng)廢棄了,只做調(diào)試用。
- 這個(gè)函數(shù)通常用來(lái)解決不可重入的代碼所引發(fā)的死鎖,然而如果可以用這個(gè)函數(shù)來(lái)解決的問(wèn)題,通常也可以用特定的隊(duì)列來(lái)解決。
7.熟悉系統(tǒng)框架,并沒(méi)有講什么東西
8.只是作為一個(gè)建議,多用塊枚舉,少用for循環(huán)
9.上面提到過(guò)Foundation框架和CoreFoundation框架,F(xiàn)oundation中NSArray等collection,CoreFoundation中也有對(duì)應(yīng)的CFArray,這兩種創(chuàng)建數(shù)組的方式也許有區(qū)別,然而“無(wú)縫橋接”技術(shù)可以使得這兩個(gè)類型之間平滑互轉(zhuǎn)。下面代碼演示了簡(jiǎn)單的無(wú)縫橋接:
NSArray *anNSArray = @[@1,@2,@3,@4,@5];
CFArrayRef aCFArray = (__bridge CFArrayRef)anNSArray;
NSLog(@"size of array =%li",CFArrayGetCount(aCFArray));
__bridge本身的意思是:ARC仍然具備這個(gè)OC對(duì)象的所有權(quán)
10.構(gòu)建緩存時(shí)選用NSCache而非NSDictionary
NSCache比NSDictonary好的地方是:當(dāng)系統(tǒng)資源將要耗盡時(shí),它可以自動(dòng)刪減緩存(刪減“最近未使用的對(duì)象”)。下面這段代碼演示了緩存的用法:
#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
創(chuàng)建NSCache時(shí),將其中可緩存的對(duì)象數(shù)目設(shè)定為100,將“總開(kāi)銷”上限設(shè)為5MB