iphone - 保存多个 map 注释 - 崩溃

标签 iphone objective-c crash nscoding

我一直在搜索顶部和底部以获取有关如何执行此操作的信息。我找到了一个很棒的教程!所以我对此还是很陌生。基本上我一直在尝试将 map View 注释存储到数组中。注释是一个单独的类,它基本上覆盖/充当 MKAnnotation用于引脚注释。它具有三个属性:

  1. Annotation Coordinate
  2. Annotation Title
  3. Annotation Subtitle


这个数组需要存储到NSUserDefaults .我遇到了一个问题,这是日志:

[UIMutableIndexPath setObject:forKey:]: unrecognized selector sent to instance 0x1187b0



存储在数组中的我的 Annotation 类对象无法保存为用户默认值。所以我不得不把这个数组变成NSData然后保存,对吧?

我有很多代码设置,只是不工作。这是我尝试所有这些的方法:

查看 Controller 类.m:
- (void)syncMap { // this method is called in viewWillDissapear (for running tests) and applicationDidEnterBackground in App Delegate

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject: localOverlays]; // this is the array I was talking about

[defaults setObject:data forKey:@"overlays"];

[defaults synchronize];

}

- (void)initCircles { // called in AppDelegate UIApplicationDelegate method: applicationDidFinishLaunchingWithOptions

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSData *data = [defaults objectForKey: @"overlays"];

    localOverlays = [NSKeyedUnarchiver unarchiveObjectWithData: data];

    if (!localOverlays) {

        // Either there is a problem or it is the first time opening the app

        localOverlays = [[NSMutableArray alloc] init];
    }

}

注意:我正在使用数组中的两个注释进行测试 (localOverlays)

所以,我的localOverlays可以编码/存档(使用 NSCoder ),因为它是 NSArray .但是,我不得不在我的 Annotation 类中添加一些进一步的设置。在其 .h 中,它用于 NSCodingMKAnnotation : 如下 < NSCoding, MKAnnotation> .对不起,如果我没有使用正确的术语。这是我的.m:
  - (void)encodeWithCoder:(NSCoder *)aCoder { // should only be called when app enters background state, but since that cannot log in the console, like before I set it up so it should also be called in viewWillDissapear

    NSLog(@"encodeCoder called in Annotation"); // gets called twice when the view will disappear... GOOD!

    [aCoder encodeObject: title forKey: @"title"];
    [aCoder encodeObject: subtitle forKey: @"subtitle"];
    [aCoder encodeDouble: coordinate.latitude forKey: @"latitude"];
    [aCoder encodeDouble: coordinate.longitude forKey: @"longitude"];
}


- (id)initWithCoder:(NSCoder *)aDecoder { // Should be called only at startup of app (not the first time you startup the app though... because data will be NULL)

    NSLog(@"In the Annotation class, initWithCoder is called"); // Does get called at appropriate times twice... NICE!

    self = [super init];

    if (self) {

        title = [aDecoder decodeObjectForKey: @"title"];
        subtitle = [aDecoder decodeObjectForKey: @"subtitle"];

        double lat = [aDecoder decodeDoubleForKey: @"latitude"];
        double lon = [aDecoder decodeDoubleForKey: @"longitude"];

        coordinate = CLLocationCoordinate2DMake(lat, lon);
    }

    return self;
}

如您所见,我已为存档设置了所有内容,对吗?好吧,似乎不是……因为现在在 ViewController 的 .m 中,我在 viewDidLoad 中也有这段代码:
    for (Annotation *pin in localOverlays) {

    if (pin) {

        NSLog(@"valid pin: _CMD updateCircles");

        [mapView addAnnotation: pin];

    }

}

当我第一次打开我的应用程序并添加引脚时,这段代码运行良好。好的,现在我已经退出 View 并退出应用程序,并从多任务栏中删除。当我重新打开它时,我在快速枚举行中遇到了崩溃:
 -[NSURL countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0xcd31140

所以,我所有的归档和编码设置都有问题。这里有什么问题......我知道这是一个冗长的问题,但我试图很好地构建它。我的代码设置是否完全不正确,我的代码中是否存在拼写错误/错误。谢谢大家!

更新:

我已经对坐标变量进行了编码,因此当我在 pin 出现在正确的坐标后启动应用程序时,但是当我尝试按下它来查看标题和副标题时,我得到了以下崩溃:
 objc_msgSend

所以有些东西被释放了……只是一个猜测……糟糕的内存管理?什么会导致我的代码崩溃?

更新:

我已经更深入地查看了我的代码并更改了一些 release周围的语句,只是改善了我的内存管理并做了一些优化。现在我得到一个更具体的崩溃:
*** -[CFString length]: message sent to deallocated instance 0x147490

所以我的标题或副标题被解除分配......为什么?我检查了我的代码,它应该是绝对没问题的,特别是因为坐标很好......

更新:

我已经解决了这个问题!我来实现,坐标两个变量,纬度和经度是 double ,数据类型......不是对象!因此,它们坚持并工作只是因为它们被复制......不像引用的对象。长话短说,我需要 retain .像这样:
        title = [[aDecoder decodeObjectForKey: @"titler"] retain];
    subtitle = [[aDecoder decodeObjectForKey: @"subtitler"] retain];

最佳答案

我不确定崩溃的确切原因是什么。但我注意到您的编码/解码方法中有一些错误:

编辑:仅当您的父类(super class)符合 NSCoding 时:

在 encodeWithCoder 中,您应该首先调用:

[super encodeWithCoder: aCoder];

在 initWithCoder 中替换
self = [super init];

经过
self = [super initWithCoder:aDecoder]

以下返回一个不可变对象(immutable对象)(不是 NSMutableArray):
  localOverlays = [NSKeyedUnarchiver unarchiveObjectWithData: data];

将此行替换为:
  localOverlays = [[NSKeyedUnarchiver unarchiveObjectWithData: data] mutableCopy];

我希望这会有所帮助!

关于iphone - 保存多个 map 注释 - 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10932871/

相关文章:

iphone - iPhone崩溃报告UUID记录在哪里?

iphone - 刷新通知中心内的 View Controller 类

iphone - 在设备上安装时如何将应用程序发送到后台?

iphone - 保存和检索图像会使应用变慢

iphone - 如何禁用/启用 UISearchBar 键盘的搜索按钮?

javascript - IE 7 崩溃并直接关闭,没有任何消息

excel - 如何防止Excel在大文件上运行宏时崩溃?

iphone - iPhone 上触发触摸事件的频率如何?

iphone - 游戏套件中回合制多人游戏的问题

iphone - 如何在 NSMutableArray 中创建查询并打印结果?