2011-09-02 81 views
0

我有以下.M一个自定义的对象类:问题与保存自定义对象NSUserDefaults的进

@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' 

回答

2

里面的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

我实际上只是在你回答之前试过这个,但仍然没有解决问题。现在我只是遇到了一场普通的事故,但它并没有告诉我在哪里。我应该使用自我吗? – Snowman

+0

您的@property是用'retain'还是'copy'声明的?其他一切似乎都是正确的。 – Joe

+0

这是宣布nonatomic,保留。 foldersContent是一个NSMutableArray,如果这有什么区别 – Snowman

0

的问题似乎是在你的initWithCoder:方法:

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

通过decodeObjectForKey:返回的值不会保留你,因为你给他们分配到高德的,而不是直接通过(据推测)retain-声明的属性,它们也不保留在那里。所以他们会在下次autorelease池耗尽时自动发布。当您尝试使用它时,恰巧曾经用于标题的内存位置现在被一个__NSArrayM对象占用;事情的工作方式稍有不同,你会得到一个更直接的EXC_BAD_ACCESS崩溃。

+0

那么解决方案是什么? – Snowman

+0

@mohabitar:显式地保留返回的对象,或者使用属性表示法(例如'self.folderTitle')将属性赋值给声明为'retain'或'copy'的属性。在调试过程中,您也可以尝试使用NSZombieEnabled,这会因访问释放的对象而导致错误更具确定性。 – Anomie

0

@Joe是正确的约需要到retain的对象,但为什么您使用的

self = [[FolderObject alloc] init]; 

代替

self = [super init]; 

你的代码的每一这就是所谓的时间会泄漏的内存块?

我不知道它是否会导致你的崩溃(我怀疑没有),但它确实很有趣。

相关问题