2010-10-27 49 views
2

所以我对Objective-C仍然很陌生,这是我现在正在更新的第一个应用程序。这个想法是这样的:整个应用程序基本上是各种东西的列表。它要求API提供15个帖子,显示那些带有Load More按钮的人。点击加载更多,它加载15多等等。它加载它们的API有一个内置超时的令牌系统。请求之间的时间太长,你必须得到一个新的令牌。所以我想要在应用程序中的任何位置使用单身人士,所以我可以只在[APIMachine getToken]和幕后执行检查自上次请求以来的时间是否过长(或者这是第一次请求),如果是,则获取新的令牌,否则返回我们已有的。我遵循我在很多地方找到的单例模式,但每当“加载更多”按钮使用[APIMachine getToken]时,它就会得到任何东西或完全随机的东西。我有它在日志中打印这些东西,有一次我甚至有一个UITableViewCell作为我的令牌。看起来变量正在被覆盖。但我真的无法弄清楚。iOS Singleton变量没有保持其值

所以在这里,它是:

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

API_open中,您将三个对象存储在实例变量中,但它们不是您拥有的对象,所以它们可能会在您需要它们的时候消失,并由不可预知的事物取代。你需要保留它们或使用适当的setter。

+0

这样做更有意义,谢谢。 – pettazz 2010-10-27 18:28:54

+1

我遇到了同样的问题 - 我想这里带走的教训是使用NSString的setter和getters,而不是Objective-C中的赋值运算符。 – 2011-05-16 20:48:17

0

您的问题是:

​​

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

创建一个单独的第二个实例是一个编程错误,应该在发展被抓。不是一个问题,你应该添加额外的代码行来隐藏。

+3

您对静态变量的评论不正确。它们被初始化为0.只有自动变量需要显式初始化。 – Chuck 2010-10-27 19:27:51