【发布时间】:2015-02-16 23:43:16
【问题描述】:
我已经在这个问题上停留了一个多星期,显然之前没有人在 stackoverflow 上报告过这个问题。在将我推荐给其他帖子之前,请仔细阅读我的描述,因为我已经阅读了所有帖子,但没有一个有我的答案。
我有一个 NSDictionary,其中包含一个 NSNumber 和一个 NSString 的 NSArray,两个键都是 NSString。
现在 NSDictionary writeToFile 崩溃并出现错误: -[NSDictionaryI isNSString]:消息发送到解除分配的实例
writeToFile 在类方法上被调用:
@implementation AppDataStore
+ (void) saveData:(NSDictionary*)dataDictionary {
NSArray *directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documents = [directories firstObject];
NSString *appDataFilePath = [documents stringByAppendingPathComponent:@"AppDataStore.plist"];
[dataDictionary writeToFile:appDataFilePath atomically:YES];
}
值得注意的是,我将 NSMutableDictionary 传递给该方法,但这不是问题,因为它可以很好地写入其他键值 NSMutableDictionaries,但不是包含 NSArray 的这个。即使我取出 NSNumber 元素,所以字典只包含一个 NSArray,writeToFile 仍然会崩溃同样的错误。在模拟器和 iPhone 上都会崩溃。
这是怎么回事?!
编辑 1(针对亚当的问题):
直到崩溃前的堆栈跟踪:
Stack trace : (
0 MedList 0x00009b39 +[AppDataStore saveData:] + 217
1 MedList 0x0000811d -[ViewController tableView:didSelectRowAtIndexPath:] + 1101
2 UIKit 0x010c894c -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1559
3 UIKit 0x010c8af7 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 285
4 UIKit 0x010cddf3 __38-[UITableView touchesEnded:withEvent:]_block_invoke + 43
5 UIKit 0x00fe20ce ___afterCACommitHandler_block_invoke + 15
6 UIKit 0x00fe2079 _applyBlockToCFArrayCopiedToStack + 415
7 UIKit 0x00fe1e8e _afterCACommitHandler + 545
8 CoreFoundation 0x00b289de __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
9 CoreFoundation 0x00b28920 __CFRunLoopDoObservers + 400
10 CoreFoundation 0x00b1e35a __CFRunLoopRun + 1226
11 CoreFoundation 0x00b1dbcb CFRunLoopRunSpecific + 443
12 CoreFoundation 0x00b1d9fb CFRunLoopRunInMode + 123
13 GraphicsServices 0x03efd24f GSEventRunModal + 192
14 GraphicsServices 0x03efd08c GSEventRun + 104
15 UIKit 0x00fb88b6 UIApplicationMain + 1526
16 MedList 0x0000681d main + 141
17 libdyld.dylib 0x02f6bac9 start + 1
18 ??? 0x00000001 0x0 + 1
)
2015-02-16 21:39:37.762 MedList[14029:496685] *** -[__NSDictionaryI isNSString__]: message sent to deallocated instance 0x7974e910
编辑 2:我又做了一些测试。我的 NSArray 中的 NSDictionary 在类方法调用之前(在 writeToFile 之前)并且仅在 didSelectRowAtIndexPath 之后被释放。为什么选择表行会自动释放数组中包含的字典?这是一种奇怪的行为。有什么想法吗?
【问题讨论】:
-
你有堆栈跟踪吗?
-
我们有理由确定它是一个失败的 NSDictionary,因为那是出现在消息中的类。 (它可以作为其他东西被释放,然后作为 NSDicitonary 重新分配,然后再次释放,但这似乎不太可能。)但是,我们不知道它是最外面的字典还是“内部”字典,在
dataDictionary中。如果在错误发生时可以停止并将调试器定位在saveData的堆栈帧中并执行po dataDictionary那么应该转储对象并且您将知道它是否已经消失或其中的某些东西。 -
我承认我以前从未做过这种调试。您能否发布一些屏幕截图来说明如何执行此操作?我已经对 po(打印对象)进行了研究,到目前为止无济于事。
-
对于
po,只需在控制台窗口中输入help。并熟悉 Xcode 左侧窗口中的堆栈显示——按下看起来像三明治的按钮,然后在线程中找到你的线程和代码的堆栈框架。
标签: ios objective-c nsdictionary writetofile