2010-10-27 54 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