iOS Singleton变量不能保持其价值

时间:2010-10-27 15:54:52

标签: objective-c singleton ios4

所以我仍然是Objective-C的新手,这是我第一个正在更新的应用程序。这个想法是这样的:整个应用程序基本上是各种各样的东西。它要求API发布15个帖子,显示那些带有“加载更多”按钮的帖子。单击“加载更多”,它会加载15个,等等。加载它们的API具有内置超时的令牌系统。请求之间的时间太长,您必须获得新令牌。所以我想在我的应用程序中的任何地方使用单例,这样我就可以[APIMachine getToken]并在幕后,它检查自上次请求以来的时间是否太长(或者这是第一个请求),如果所以,得到一个新的令牌,否则返回我们已经拥有的令牌。我正在遵循我在很多地方找到的单例模式,但每次“加载更多”按钮使用[APIMachine getToken]时,它都会获得任何内容或完全随机的内容。我把它打印在日志中,有一次我甚至得到了一个UITableViewCell作为我的令牌。看起来变量被某种方式覆盖了。但我真的无法弄明白。

所以这是:

static PoorAPI2 *_instance;
@implementation PoorAPI2

@synthesize apiToken, timeOpened, tokenTTL;

+ (PoorAPI2*)sharedAPI
{

    @synchronized(self) {
        if (_instance == nil) {         
            _instance = [[super allocWithZone:NULL] init];
        }
    }
    return _instance;
}

-(NSString *)API_open{

    //boring code to get api token redacted

if ([doneness isEqualToString:@"success"]) {
    NSDictionary *data = [json objectForKey:@"data"];
    apiToken = [data objectForKey:@"api_token"];
    tokenTTL = [data objectForKey:@"ttl"];
    timeOpened = [NSDate date];

}else{
    NSLog(@"FFFFFFFUUUUUUUUUUUU this error should be handled better.");
}

return apiToken;    
}

-(BOOL)isConnectionOpen{
    return ([timeOpened timeIntervalSinceNow]  > tokenTTL);
}

-(NSString *)getToken{
    if([self isConnectionOpen]){
        return apiToken;
    }else{
        return [_instance API_open];
    }
}

-(id)init{
    if(self = [super init]){
        apiToken = [[NSString alloc] initWithString:@""];
        timeOpened = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
        tokenTTL = 0;
    }
    return self;
}

+ (id)allocWithZone:(NSZone *)zone
{   
    return [[self sharedAPI]retain];    
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;    
}

- (id)retain
{   
    return self;    
}

- (unsigned)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;    
}

@end

我只能希望我做一些非常愚蠢的事情,这将是一个热闹的点对点笑话。然后至少我的应用程序将工作。

2 个答案:

答案 0 :(得分:2)

API_open中,您将三个对象存储在实例变量中,但它们不是您拥有的对象,因此它们可能会在您需要它们时消失,并被不可预测的内容替换。你需要保留它们或使用适当的制定者。

答案 1 :(得分:0)

你的问题是:

static PoorAPI2 *_instance;

C,并且通过继承Objective-C,不要初始化变量。只需改为:

static PoorAPI2 *_instance = nil;

此外,我也是学校,添加额外的代码以防止将单例作为单个使用是完全浪费时间,并且只为您提供更多可能存在错误的代码。

所以,如果我是你,那么我会从+[PoorApi2 allocWithZone:]中删除所有方法。 Objective-C是一种动态语言,如果客户想要实例化你的单例的第二个实例,那么尽管你浪费了额外的代码行,它仍然可以这样做。我最多会添加一个这样的日志:

-(id)init{
    if (_instance) NSLog(@"WARNING: PoorAPI2 already has a shared instance.");
    if(self = [super init]){
        apiToken = [[NSString alloc] initWithString:@""];
        timeOpened = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
        tokenTTL = 0;
    }
    return self;
}

创建单例的第二个实例是编程错误,应该在开发中捕获。不是问题,你应该添加额外的代码行来隐藏。

相关问题