Проблема с сохранением пользовательского объекта в NSUserDefaults - PullRequest
0 голосов
/ 02 сентября 2011

У меня есть собственный класс объектов со следующим .m:

@implementation FolderObject

    @synthesize folderTitle, folderContents; //title is NSString, contents is array

    - (id)init
    {
        self = [super init];
        if (self) {
        }
        return self;
    }

    - (void)encodeWithCoder:(NSCoder *)coder {
        [coder encodeObject:foldersContents forKey:@"foldersContents"];
        [coder encodeObject:folderTitle forKey:@"folderTitle"];

    }
    - (id)initWithCoder:(NSCoder *)coder {
        self = [[FolderObject alloc] init];
        if (self != nil)
        {
            foldersContents = [coder decodeObjectForKey:@"foldersContents"];
            folderTitle = [coder decodeObjectForKey:@"folderTitle"]; 
        }   
        return self;
    }
    @end

Вот как я использую папку (в каком-то другом классе):

FolderObject *newFolder=[FolderObject alloc];
        newFolder.folderTitle=[textView text];
        newFolder.folderContents=[[NSMutableArray alloc]init];

        [folders addObject:newFolder];

Вот какЯ сохраняю и извлекаю пользовательский объект из NSUserDefaults:

-(void)viewDidDisappear:(BOOL)animated
{
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:folders] forKey:@"folders"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
-(void)viewWillAppear:(BOOL)animated
{
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    NSData *dataRepresentingSavedArrayFolders = [currentDefaults objectForKey:@"folders"];
    if (dataRepresentingSavedArrayFolders != nil)
    {
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArrayFolders];
        if (oldSavedArray != nil) {
            folders = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        }
        else {
            folders = [[NSMutableArray alloc] init];
        }
    }

    else folders=[[NSMutableArray alloc] init];

И, наконец, вот где проблема:

        FolderObject *newFolder=[folders objectAtIndex:indexPath.row];
        [folderTitleLabel setText:newFolder.folderTitle];

Во второй строке я получаю сообщение об ошибке во время выполнения, нотолько после того, как я выйду из приложения и вернусь.Когда я добавляю объекты в массив папок и вызываю вышеизложенное, проблем не возникает.Но если я выйду из приложения и вернусь, то возникнут проблемы:

 -[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x4b9e400
2011-09-02 08:09:24.290 MyApp[43504:b303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x4b9e400'

Ответы [ 3 ]

2 голосов
/ 02 сентября 2011

Внутри initWithCoder: для вашего FolderObject вы неправильно сохраняете значения, которые приведут к вашей аварии. Убедитесь, что вы используете это свойство следующим образом.

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self != nil)
    {
        //dot notation (self.) will properly retain or copy your string
        //as long as it is declared as retain or copy (I recommend copy)
        self.foldersContents = [coder decodeObjectForKey:@"foldersContents"];
        self.folderTitle = [coder decodeObjectForKey:@"folderTitle"]; 
    }   
    return self;
}
0 голосов
/ 02 сентября 2011

@ Джо прав насчет необходимости retain объектов, но почему вы используете

self = [[FolderObject alloc] init];

вместо

self = [super init];

Ваш код будет пропускать кусок памяти каждый разэто называется?

Я не знаю, вызывает ли это ваш сбой (я подозреваю, что нет), но это, безусловно, интересно.

0 голосов
/ 02 сентября 2011

Проблема, похоже, в вашем initWithCoder: методе:

        foldersContents = [coder decodeObjectForKey:@"foldersContents"];
        folderTitle = [coder decodeObjectForKey:@"folderTitle"]; 

Значения, возвращаемые decodeObjectForKey:, не сохраняются для вас, и, поскольку вы присваиваете их иварам напрямую, а не через (предположительно) retain -объявленные свойства, они также не сохраняются там. Таким образом, они автоматически освобождаются при следующем сливе пула автоматического выпуска. К тому времени, когда вы пытаетесь его использовать, случается так, что область памяти, ранее использовавшаяся для заголовка, теперь занята объектом __NSArrayM; если бы все получилось немного иначе, вы бы получили более простой сбой EXC_BAD_ACCESS.

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