// MyClass.h
#import <Foundation/Foundation.h>
@interface MyClass : NSObject <NSCoding> {
NSString *string1;
NSString *string2;
}
@property (nonatomic, retain) NSString *string1;
@property (nonatomic, retain) NSString *string2;
@end
这是m文件。
// MyClass.m
#import "MyClass.h"
@implementation MyClass
@synthesize string1, string2;
- (void)encodeWithCoder:(NSCoder *)coder;
{
if (self = [super init]){
[coder encodeObject:string1 forKey:@"string1"];
[coder encodeObject:string2 forKey:@"string2"];
}
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[MyClass alloc] init];
if (self != nil)
{
string1 = [coder decodeObjectForKey:@"string1"];
string2 = [coder decodeObjectForKey:@"string2"];
}
return self;
}
- (void)viewDidUnload {
self.string1 = nil;
self.string2 = nil;
}
- (void)dealloc {
[super dealloc];
[string1 release];
[string2 release];
}
@end
我创建了这样的对象数组:
MyClass *object1 = [[MyClass alloc] init];
object1.string1 = @"object1 string1";
object1.string2 = @"string1 string2";
MyClass *object2 = [[MyClass alloc] init];
object2.string1 = @"object2 string1";
object2.string2 = @"object2 string2";
theArray = [[NSMutableArray alloc] initWithObjects:object1, object2, nil];
然后我像这样保存了数组:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:theArray] forKey:@"savedArray"];
然后我像这样从磁盘加载数组。
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
{
theArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
}
else {
theArray = [[NSMutableArray alloc] init];
}
}
程序在- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
cell.textLabel.text = [[theArray objectAtIndex:indexPath.row] string1];
为什么会在那里崩溃?如果我不从NSUserDefaults加载数组,它不会崩溃。但是,我没有看到任何我在保存或加载数组时遇到的错误。
编辑: 我也可以使用这行代码崩溃:
NSLog(@"%@", [[theArray objectAtIndex:0] string1]) ;
答案 0 :(得分:6)
除了cobbal的优点之外,你的initWithCoder:
方法不使用setter,因此不会保留字符串。当您尝试在崩溃线上访问string1
时,该字符串可能已经被释放。请在initWithCoder:
中执行此操作:
self.string1 = [coder decodeObjectForKey:@"string1"];
self.string2 = [coder decodeObjectForKey:@"string2"];
要解决cobbal的第一点,请不要在encodeWithCoder:
中完成任何初始化。只需编码您的对象。有关编码和解码对象的更多详细信息,请查看Apple's Archives and Serializations Programming Guide for Cocoa。
答案 1 :(得分:3)
我突然想到了一些事情
init
中呼叫encodeWithCoder:
。由于您未在此处初始化任何内容,因此不应更改self
alloc
中呼叫initWithCoder:
。一旦进入init方法,就不必调用alloc,只需调用self = [super init]
。viewDidUnload
方法。即使在NSObject子类中调用它,您可能也不希望在卸载视图时删除数据。[super dealloc]
。它应该结束。答案 2 :(得分:1)
我没有阅读您的所有代码,因此我不确定这是否是问题,但在dealloc
中,您应该仅在释放实例变量后调用[super dealoc]
。
答案 3 :(得分:0)
如果由于超出范围而崩溃,请检查您的UITableViewController是否正确实现
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
和
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
反映您正在使用的NSArray作为数据源。