Использование синглтона и его архивирование - PullRequest
1 голос
/ 17 февраля 2011

У меня есть класс, в котором я хочу сохранить постоянные настройки во всем приложении. Этот класс определяется как:

@interface Archive : NSCoder <NSCoding> {
    NSString *fromAddress;
    NSString *toAddress;
... more ...
}

@property(nonatomic,retain) NSString *fromAddress;
@property(nonatomic,retain) NSString *toAddress;

+ (Archive *)sharedArchive;

-(void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;

И реализовано как:

@synthesize fromAddress, toAddress;

+ (Archive *)sharedArchive
{
    if (sharedArchive == nil) {
        NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:@"mydata"];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        sharedArchive = [unarchiver decodeObjectForKey:@"myapp"];
        [unarchiver finishDecoding];
    }
    return sharedArchive;
}

+ (id)allocWithZone:(NSZone *)zone
{
    sharedArchive = [super allocWithZone:NULL];
    return sharedArchive;
}

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

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return NSUIntegerMax; 
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.fromAddress forKey:@"fromAddress"];
    [aCoder encodeObject:self.toAddress forKey:@"toAddress"];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [self initWithCoder:aDecoder];
    fromAddress = [[aDecoder decodeObjectForKey:@"fromAddress"] retain];
    toAddress = [[aDecoder decodeObjectForKey:@"toAddress"] retain];
    return self;
}

Метод приложения-делегата applicationWillTerminate:

- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:[Archive sharedArchive] forKey:@"myapp"];
    [archiver finishEncoding];
    [data writeToFile:@"myapp" atomically:YES];
}

Я новичок в этой концепции архивирования / разархивирования. Проблема в том, что я не могу прочитать обратно из файла данных. Я получаю следующую ошибку:

- [NSKeyedUnarchiver initForReadingWithData:]: данные имеют значение NULL

Может ли кто-нибудь объяснить, что я делаю не так? Или, возможно, лучший способ сохранить / восстановить постоянные данные. Я изучил класс NSUserDefaults, но не думаю, что это подходит для моего случая ... Я не пытаюсь сохранить пользовательские настройки.

Ответы [ 2 ]

1 голос
/ 17 февраля 2011

Вы хотите сохранить только эти две строки? Используйте NSUserDefaults.

если вы не хотите использовать NSUserDefaults, вы должны указать реальные пути вместо @ "myapp" для writeToFile и readFromFile.

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [libraryPath stringByAppendingPathComponent:@"myApp"];
[data writeToFile:path atomically:YES];

и вы также должны выпустить NSMutableData *data и NSKeyedUnarchiver *unarchiver

Кстати, [writeToFile:atomically:] возвращает BOOL, который сообщает вам, была ли запись успешной.

btw2, - (void)applicationWillTerminate:(UIApplication *)application не будет часто вызываться на iOS4 с включенной многозадачностью. Вы также должны поместить свою функцию сохранения в applicationDidEnterBackground:.

0 голосов
/ 17 февраля 2011

@ fluchtpunkt правильно понял;«Вы хотите сохранить только эти две строки? Используйте NSUserDefaults.»

Или, более конкретно, если:

имеет класс, в котором я хочу сохранить постоянные настройки во всем приложении.

Если вам не нужно сохранять какое-то значительное количество данных - большие BLOB-объекты или тому подобное - вы должны использовать NSUserDefaults.

Использование архивирования и разархивирования при завершении работы приложения / запуске приложения сопряжено с потенциальными проблемами.Приложения не всегда корректно завершаются, и разархивирование при запуске нескольких вещей, которые используются «во всем приложении» (т. Е. , а не используется для запуска приложения), просто замедлит время запуска приложения.

Если у вас действительно имеется какое-то большое количество состояний, которое необходимо сохранить между запусками, то архивирование / разархивирование, безусловно, может работать.Тем не менее, вы должны не связывать архив с окончанием;Вы действительно хотите, чтобы пользователь потерял данные, когда приложение принудительно закрывается, сбрасывается или устройство перезагружается (что многие пользователи имеют неестественный фетиш для выполнения)?

...