线程安全的单例和非原子属性问题

时间:2012-09-12 11:48:02

标签: objective-c multithreading ios5 singleton atomicity

我有一个问题,如下所述和解决方案。但我认为我们的解决方案并不是解决这个问题的“正确方法”。

1:我有数据

的线程安全单例
//DataSingleton.h
@interface DataSingleton : NSObject
@property (nonatomic, readonly, retain) NSString *userLogin;
-(void)setPrettyLogin:(NSString*)prettyLogin;
@end

//DataSingleton.m
#import "DataSingleton.h"

@synthesize userLogin   = _userLogin;

+(id)sharedSingleton{

    static dispatch_once_t DataSPred;
    static DataSingleton *shared = nil;
    dispatch_once(&DataSPred, ^{ shared = [[self alloc] init]; });
    return shared;
}

-(void)setPrettyLogin:(NSString*)prettyLogin{
    _userLogin = prettyLogin;
}

@end

2:我也有相同的网络单身,我使用功能

[NSURLConnection sendAsynchronousRequest:request 
     queue:[NSOperationQueue mainQueue] 
     completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) 
         { <block> }];
// I know about mainQueue - only for UI. Here it is, for clarity.

3:问题

当我尝试在NSURLConnection块(在NetworkSingleton方法之一)中获取 [[DataSingleton sharedSingleton] userLogin] 时 - 我得到同样的时间并且在 _userLogin 中我发现了一些垃圾=(

4:解决方案不好

我花了大约一个小时,但没有为我的问题找到正确的答案。并创建这个:

//DataSingleton.h
@interface DataSingleton : NSObject{
    NSString* _userLogin;
}

-(NSString*)userLogin;
-(void)setPrettyLogin:(NSString*)prettyLogin;
@end

//DataSingleton.m
#import "DataSingleton.h"

+(id)sharedSingleton{

    static dispatch_once_t DataSPred;
    static DataSingleton *shared = nil;
    dispatch_once(&DataSPred, ^{ shared = [[self alloc] init]; });
    return shared;
}

-(NSString*)userLogin{
    return _userLogin;
}

-(void)setPrettyLogin:(NSString*)prettyLogin{

    _userLogin = [prettyLogin retain];
    //I can,t release it and 
    //static code analysis is not happy with what is happening
}

@end

有人有想法吗?

祝你好运 塞吉

1 个答案:

答案 0 :(得分:1)

您必须在设置器中保留该值。实际上这个问题与线程无关。

你的功能几乎是正确的。

-(void)setPrettyLogin:(NSString*)prettyLogin {
    _userLogin = [prettyLogin retain];
}

但它应该是

-(void)setPrettyLogin:(NSString*)prettyLogin {
    if (_userLogin != prettyLogin) {
         NSString *tmp = _userLogin;
         _userLogin = [prettyLogin retain];
         [tmp release];
    } 
}

-(void)dealloc {
    [_userLogin release];
    [super dealloc];
}

现在,如果您不想发布值调用

[[DataSingleton sharedSingleton] setPrettyLogin:nil];