Question

Selon Apple Docs Nscalendar n'est pas. Comment puis-je assurer la sécurité des threads lorsque j'utilise le méthode statique currentCalendar ?

Toute bibliothèque pourrait appeler la même méthode. Comment puis-je verrouiller l'accès?

Était-ce utile?

La solution

Vous pouvez utiliser NSLOCK.

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

et

[lock lock];
//calendar
[lock unlock];

Autres conseils

Je m'attendrais à ce que la création d'un calendrier soit sécurisée (chaque fois-ci-courant, vous êtes appelé une nouvelle instance), la mutation d'une instance ne le ferait pas simultanément.

Vous voudrez peut-être utiliser un proxy pour envelopper toutes les méthodes dans un bloc synchronisé. Voir ma classe bmproxy ci-dessous (avec ThreadSafe réglé sur oui). J'utilise cette classe pour réutiliser NSDateFormatters et NSCalendars sur plusieurs threads et cela fonctionne comme un charme. Vous pouvez également l'utiliser pour d'autres classes sans fil.

L'utilisation est par exemple comme suit:

+ (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;
}

La classe 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top