2012-03-01 73 views

回答

0

您可以使用NSLock。

NSLock *lock = [[NSLock alloc] init]; 

[lock lock]; 
//calendar 
[lock unlock]; 
+0

真。我可以使用鎖來自己使用該功能。但是如果一個庫或任何「不是我的代碼」的東西正在使用該方法呢? – 2012-03-01 14:47:54

+0

不應該「不是你的代碼」照顧自己嗎?只需在文檔中告訴您的方法不是線程安全的。畢竟蘋果是這麼做的。 – ayoy 2012-03-01 15:27:37

0

我希望,創造一個日曆將是線程安全的(每次-currentCalendar叫你得到一個新的實例),同時變異的一個實例不會。

0

您可能希望使用代理來包裝同步塊中的所有方法。請參閱下面的我的類BMProxy(將threadSafe設置爲YES)。我使用這個類來重複使用跨多個線程的NSDateFormatters和NSCalendars,這就像一個魅力。您也可以將它用於其他非線程安全類的實例。

用法是舉例如下:

+ (NSCalendar *)threadSafeCalendar { 
    static NSCalendar *calender = nil; 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSCalendar *c = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
     [c setTimeZone:[NSTimeZone timeZoneWithName:@"CET"]]; 
     calender = (NSCalendar *)[BMProxy proxyWithObject:c threadSafe:YES retained:YES]; 
    }); 
    return calender; 
} 

的BMProxy類:

#import <Foundation/Foundation.h> 

/** 
Proxy that delegates all messages to the specified object 
*/ 
@interface BMProxy : NSProxy { 
@private 
    __weak NSObject *_object; 
    __strong NSObject *_retainedObject; 
    BOOL _threadSafe; 
} 

/** 
The target object of the proxy. 
*/ 
@property(readonly, weak) NSObject *object; 

/** 
Whether the proxy should be thread-safe (make all methods synchronized) or not. 
*/ 
@property(atomic, assign) BOOL threadSafe; 

/** 
Initializer with the designated target object. 

Defaults to threadSafe = NO and retained = YES. 

@param object The proxied object 
*/ 
- (id)initWithObject:(NSObject *)object; 

/** 
Initializer with the designated target object and whether the proxy should be thread-safe or not. 

Defaults to retained = YES. 

@param object The proxied object 
@param threadSafe Whether the proxy should synchronize all methods or not. 
*/ 
- (id)initWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe; 

/** 
Designated initializer. 

The retained parameter determines whether the target object is retained or not. 
*/ 
- (id)initWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained; 

+ (BMProxy *)proxyWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained; 

@end 

@implementation BMProxy 

@synthesize threadSafe = _threadSafe; 
@synthesize object = _object; 

+ (BMProxy *)proxyWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained { 
    return [[BMProxy alloc] initWithObject:object threadSafe:threadSafe retained:retained]; 
} 

- (id)initWithObject:(NSObject *)theObject { 
    return [self initWithObject:theObject threadSafe:NO retained:YES]; 
} 

- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)b { 
    return [self initWithObject:theObject threadSafe:b retained:YES]; 
} 

- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)b retained:(BOOL)retained { 
    _object = theObject; 
    if (retained) { 
     _retainedObject = theObject; 
    } 
    self.threadSafe = b; 
    return self; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 
    return [_object methodSignatureForSelector:aSelector]; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation { 
    if (self.threadSafe) { 
     @synchronized(_object) { 
      [anInvocation setTarget:_object]; 
      [anInvocation invoke]; 
     } 
    } else { 
     [anInvocation setTarget:_object]; 
     [anInvocation invoke]; 
    } 
} 

- (BOOL)respondsToSelector:(SEL)aSelector { 
    BOOL responds = [super respondsToSelector:aSelector]; 
    if (!responds) { 
     responds = [_object respondsToSelector:aSelector]; 
    } 
    return responds; 
} 

@end