【问题标题】:Why does this crash?为什么会崩溃?
【发布时间】:2010-09-19 14:03:07
【问题描述】:

我上课了。这是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]) ;

【问题讨论】:

  • 什么异常导致了崩溃?您是否确保 theArray 没有超出索引,例如- tableView:numberOfRowsInSection: 设置正确吗?
  • 没有给出错误信息,程序直接退出。如果我使用调试器,我会看到消息 Program received signal: “EXC_BAD_ACCESS”。 tableView:numberOfRowsInSection 返回 1。

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


【解决方案1】:

除了 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 了解有关编码和解码对象的更多详细信息。

【讨论】:

  • 谢谢,解决了!如果字符串已经合成,为什么不使用 setter 和 getter?
  • @awakeFromNib 因为 self.string1 实际上是 [self setString1] 的语法糖。写string1不能调用那个方法,怎么知道是方法?
  • @synthesize 语句有效地为您编写了 setter 和 getter 方法;您仍然可以给他们打电话。正如 ustun 所指出的,self.string1=@"z" 被替换为 [self setString1:@"z"] 而 string1=@"z" 只是设置 string1 而不调用设置器。
【解决方案2】:

我突然想到了一些事情

  • 您在encodeWithCoder: 中呼叫init。因为你没有在这里初始化任何东西你不应该改变self
  • 您在initWithCoder: 中呼叫alloc。进入 init 方法后,您不必调用 alloc,只需调用 self = [super init]
  • 你有一个viewDidUnload 方法。即使在 NSObject 子类中调用它,您也可能不想在视图卸载时删除您的数据。
  • 您在 dealloc 方法的开头调用了[super dealloc]。它应该在最后。

【讨论】:

  • 你的第一点我该怎么办?我应该删除 if (self = [super init]) 吗?我试过了,它没有用。我根据您的其他观点进行了更改,但没有一个修复它。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    

    反映您用作数据源的 NSArray。

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 2013-01-31
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 2011-04-17
      相关资源
      最近更新 更多