Переменные iOS Singleton не сохраняют свои значения - PullRequest
2 голосов
/ 27 октября 2010

Так что я все еще новичок в Objective-C, и это было мое первое приложение, которое я сейчас обновляю.Идея такова: все приложение представляет собой разные списки вещей.Он запрашивает у API 15 сообщений, показывает те, у которых есть кнопка «Загрузить еще».Нажмите Load More, он загружает еще 15 и т. Д. API, из которого они загружаются, имеет систему токенов со встроенным тайм-аутом. Слишком долго между запросами, и вам нужно получить новый токен.Поэтому я хочу, чтобы синглтон использовался в любом месте моего приложения, чтобы я мог просто сделать [APIMachine getToken] и за кадром он проверяет, было ли время с момента последнего запроса слишком длинным (или это первый запрос), если так,получает новый токен, в противном случае возвращает тот, который у нас уже есть.Я следую одноэлементному шаблону, который я нашел во многих местах, но каждый раз, когда кнопка Load More использует [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 ]

2 голосов
/ 27 октября 2010

В API_open вы сохраняете три объекта в переменных экземпляра, но они не являются объектами, которыми вы владеете, поэтому они, вероятно, исчезнут к тому времени, когда они вам понадобятся, и будут заменены чем-то непредсказуемым. Вам нужно сохранить их или использовать правильные сеттеры.

0 голосов
/ 27 октября 2010

Ваша проблема:

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

Создание второго экземпляра синглтона является ошибкой программирования и должно быть поймано при разработке.Не проблема, вы должны добавить дополнительные строки кода, чтобы скрыть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...