iOS开发技巧

iOS线程安全

2017-03-10  本文已影响232人  勇往直前888

UIKit是线程不安全的

这个章节的内容都是这篇文章的节选

void PSPDFAssertIfNotMainThread(void) { 
    NSAssert(NSThread.isMainThread, 
      @"Error: Method needs to be called on the main thread. %@", 
      [NSThread callStackSymbols]); 
} 
// header 
@property (nonatomic, strong) NSMutableSet *delegates; 
 
// in init 
_delegateQueue = dispatch_queue_create("com.PSPDFKit.cacheDelegateQueue", 
  DISPATCH_QUEUE_CONCURRENT); 
 
- (void)addDelegate:(id<PSPDFCacheDelegate>)delegate { 
    dispatch_barrier_async(_delegateQueue, ^{ 
        [self.delegates addObject:delegate]; 
    }); 
} 
 
- (void)removeAllDelegates { 
    dispatch_barrier_async(_delegateQueue, ^{ 
        self.delegates removeAllObjects]; 
    }); 
} 
 
- (void)callDelegateForX { 
    dispatch_sync(_delegateQueue, ^{ 
        [self.delegates enumerateObjectsUsingBlock:^(id<PSPDFCacheDelegate> delegate, NSUInteger idx, BOOL *stop) { 
            // Call delegate 
        }]; 
    }); 
} 

_delegateQueue的类型是 dispatch_queue_t,在其他地方定义,应该是个内部成员变量

// header 
@property (atomic, copy) NSSet *delegates; 
 
- (void)addDelegate:(id<PSPDFCacheDelegate>)delegate { 
    @synchronized(self) { 
        self.delegates = [self.delegates setByAddingObject:delegate]; 
    } 
} 
 
- (void)removeAllDelegates { 
    self.delegates = nil; 
} 
 
- (void)callDelegateForX { 
    [self.delegates enumerateObjectsUsingBlock:^(id<PSPDFCacheDelegate> delegate, NSUInteger idx, BOOL *stop) { 
        // Call delegate 
    }]; 
} 

实际的例子

在weex的SDK中有线程安全的字典和数组,以字典为例:

/**
 *  @abstract Thread safe NSMutableDictionary
 */
@interface WXThreadSafeMutableDictionary<KeyType, ObjectType> : NSMutableDictionary

@end
  • 这个可以讨论,可以直接从NSObject过来,不过要重新设计一下对外的接口。本人更倾向于这种组合模式,接口可以自定义,按照需求来,用特殊的名字,防止使用过度。更有定制化的味道。比如key规定为NSString类型
@interface WXThreadSafeMutableDictionary ()

@property (nonatomic, strong) dispatch_queue_t queue;
@property (nonatomic, strong) NSMutableDictionary* dict;

@end
- (instancetype)initCommon {
    self = [super init];
    if (self) {
        NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.dictionary_%p", self];
        _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}

NSStringUTF8String是不一样的,GCDc函数

- (id)objectForKey:(id)aKey {
    __block id obj;
    dispatch_sync(_queue, ^{
        obj = _dict[aKey];
    });
    return obj;
}
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    aKey = [aKey copyWithZone:NULL];
    dispatch_barrier_async(_queue, ^{
        _dict[aKey] = anObject;
    });
}
- (id)copy {
    __block id copyInstance;
    dispatch_sync(_queue, ^{
        copyInstance = [_dict copy];
    });
    return copyInstance;
}

同步机制

保证线程安全的措施。下面两篇文章不错:
iOS中保证线程安全的几种方式与性能对比
iOS开发里的线程安全机制

Foundation对象

GCD方式

小结

上一篇 下一篇

猜你喜欢

热点阅读