52个编写高质量iOS有效方法(41-50)

倒计时回家还剩下两天

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容