美文网首页iOS
52个编写高质量iOS有效方法(41-50)

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

作者: SpursGo | 来源:发表于2017-01-24 11:54 被阅读19次

    倒计时回家还剩下两天

    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

    相关文章

      网友评论

        本文标题:52个编写高质量iOS有效方法(41-50)

        本文链接:https://www.haomeiwen.com/subject/vbjzbttx.html