ios - 加载时 heightForRowAtIndexPath 偶尔会崩溃,NSCoding - iOS

标签 ios cocoa nscoding heightforrowatindexpath

关于我保存数据的方式的一些信息:我有一个由用户添加和删除的 View Controller 数组(这基本上是一个笔记应用程序, View Controller 是文件夹)。 View Controller 有几个应用程序需要保存的动态属性以及其中的注释数组,然后注释对象本身有一些需要保存的属性。 View Controllers 和 Notes 当然都有适当的 NSCoding 东西,例如 View Controllers:

- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.folderName forKey:@"lvcTitle"];
    [encoder encodeObject:[NSNumber numberWithInt:self.myPosition] forKey:@"myPosition"];
    [encoder encodeObject:self.notes forKey:@"notes"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self.folderName = [decoder decodeObjectForKey:@"lvcTitle"];
    NSNumber *gottenPosition = [decoder decodeObjectForKey:@"myPosition"];
    int gottenPositionInt = [gottenPosition intValue];
    self.myPosition = gottenPositionInt;
    self.notes = [decoder decodeObjectForKey:@"notes"];
    return self; }

Controller 数组属于单例类。 NSCoding 对我来说很困惑,尽管它被认为是简单的东西,但到目前为止,我已经成功地只告诉 Singleton 保存 Controllers 数组——然后(成功地)保存了 View Controllers 的所有包含的属性,它们的属性以及注释的所有属性。这是单例中的代码:

- (void) saveDataToDisk:(id)object key:(NSString *)key {
    NSString *path = [self pathForDataFile];

    NSMutableDictionary *rootObject;
    rootObject = [NSMutableDictionary dictionary];

    [rootObject setValue:object forKey:key];
    [NSKeyedArchiver archiveRootObject:rootObject toFile:path]; } 

- (void) loadDataFromDisk {
    NSString *path = [self pathForDataFile];
    NSDictionary *rootObject;

    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    

    if ([rootObject valueForKey:@"controllers"] != nil) {
        self.controllers = [NSMutableArray arrayWithArray:[rootObject valueForKey:@"controllers"]];
        firstRun = false;

        LabeledViewController *lastOneThere = [self.controllers objectAtIndex:self.controllers.count-1];
        lastOneThere.isFolderAddView = TRUE;

    }else{
        firstRun = true;
    } 
}

然后我在文件夹 View Controller 中多次调用保存方法:

[singleton saveDataToDisk];

这会运行好几次,直到我在加载应用程序时随机崩溃。罪魁祸首是 heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

Note *currentNote = [self.notes objectAtIndex:indexPath.row];
if (currentNote.associatedCellIsSelected) {
    return currentNote.myHeight + NOTE_BUTTON_VIEW_HEIGHT;
}

return NORMAL_CELL_FINISHING_HEIGHT;  }

我收到以下错误:

2012-06-07 08:28:33.694 ViewTry[1415:207] -[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710
2012-06-07 08:28:33.696 ViewTry[1415:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710'
*** First throw call stack:

我知道“__NSCFString”和“无法识别的选择器发送到实例”意味着在某处不应该有一个字符串,因为 associatedCellIsSelected 是一个 bool 值。但是,如果我只在 heightForRow 中返回“currentNote.myHeight”,我也会得到与 myHeight 相同的 __NSCF 错误,这是一个 float 。如果我一起取出 heightForRow ,除了适当的高度定义外,一切都有效。

顺便说一句,heightForRowAtIndexPath 引用的 TableView 是在创建并填充注释数组后在 loadView 中创建的。我只是不明白为什么这个错误只会偶尔弹出(比如 5-10 次打开、保存、关闭和重新打开应用程序),看似随机 - 我找不到导致此行为的模式。有什么指点吗?

抱歉弄得一团糟,我是 iOS 编程的新手,我确定我在这里做错了很多事情。

编辑 - 此外,一旦应用程序崩溃,每次我重新打开它时它都会崩溃(除非我禁用 heightForRow),直到我卸载并重新安装它。

最佳答案

当您看到“无法识别的选择器”错误并且接收者类型不是您编码的对象类型(在本例中为 __NSCFString 而不是 Note)时,很可能您会遇到问题,您打算使用的对象已过早释放,并且其地址空间被重新用于分配新对象。

修复取决于追踪额外释放发生的地方(或保留没有发生的地方)。如果您可以显示 notes 的 @property 声明,它可能会更清楚地说明情况。

一件快速的事情是从菜单中选择 Product->Analyze 并修复它标记的任何内容。它不会捕获所有内容,但它是一个很好的开始检查。

关于ios - 加载时 heightForRowAtIndexPath 偶尔会崩溃,NSCoding - iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10903817/

相关文章:

ios - NSCoder + UIDocument : are they compatible?

ios - NSCoding 和保存/加载默认值问题

ios - 在 iOS 上,缓存绘制的屏幕图像并显示它的最快方法是什么?

ios - 为什么一个 UIStackView 单 View ,按比例填充,Layout Margins 会导致不明确的约束错误?

ios - KVO和NSNotificationCenter的正确用法和区别是什么?

iphone - 创建 NSAutoreleasePool 的成本有多高

cocoa - bool 值作为 Cocoa 中的属性

jquery - 如何在 PhoneGap 应用程序中使用 ONSEN-UI 实现 iOS 类型的 ON SWIPE DELETE 功能?

python - 在 Python 中使用 dock 的基本 cocoa 应用程序,但不使用 Xcode 和所有其他功能

ios - 编码复杂对象 swift 3.0