为什么会崩溃?

时间:2010-09-19 14:03:08

标签: objective-c cocoa-touch crash nsmutablearray nsuserdefaults

我上了课。这是h文件。

//  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]) ;

4 个答案:

答案 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子类中调用它,您可能也不希望在卸载视图时删除数据。
  • 您在dealloc方法的开头调用了[super dealloc]。它应该结束。

答案 2 :(得分:1)

我没有阅读您的所有代码,因此我不确定这是否是问题,但在dealloc中,您应该仅在释放实例变量后调用[super dealoc]

答案 3 :(得分:0)

如果由于超出范围而崩溃,请检查您的UITableViewController是否正确实现

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

反映您正在使用的NSArray作为数据源。