倒计时回家还剩下两天
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