保存多个地图注释 - 崩溃

时间:2012-06-07 13:32:04

标签: iphone objective-c crash nscoding

我一直在上下搜索有关如何执行此操作的信息。我登上了一个很棒的教程!所以我仍然是新手。基本上我一直在尝试将Map View注释存储到数组中。注释是一个单独的类,它基本上覆盖/充当引脚注释的MKAnnotation。它有三个属性:

  
      
  1. 注释坐标
  2.   
  3. 注释标题
  4.   
  5. 注释字幕
  6.   

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

  

[UIMutableIndexPath setObject:forKey:]:发送到的无法识别的选择器   实例0x1187b0

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

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

View Controller Class.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];

    }

}

这个代码在我第一次打开我的应用程序并添加引脚时工作得很好。好的,现在我退出了视图并退出了应用程序,并从多任务栏中删除了。当我打开它时,我在快速枚举行中崩溃了:

 -[NSURL countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0xcd31140

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

更新:

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

 objc_msgSend

所以有些东西正确发布......只是一个猜测...糟糕的内存管理?什么会导致我的代码崩溃?

更新:

我更深入地研究了我的代码并更改了一些release语句,只是改进了我的内存管理并完成了一些优化。现在我得到了一个更具体的崩溃:

*** -[CFString length]: message sent to deallocated instance 0x147490

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

更新:

我已经解决了这个问题!我来实现,坐标两个变量,纬度和经度都是双打,数据类型...... NOT对象!因此,他们坚持并且只是工作,因为他们被复制......不像参考的对象。长话短说我需要retain。就像这样:

        title = [[aDecoder decodeObjectForKey: @"titler"] retain];
    subtitle = [[aDecoder decodeObjectForKey: @"subtitler"] retain];

2 个答案:

答案 0 :(得分:1)

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

编辑:只有你的超级类符合NSCoding:

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

[super encodeWithCoder: aCoder];

在initWithCoder中替换

self = [super init];

通过

self = [super initWithCoder:aDecoder]

以下命令返回一个不可变对象(不是NSMutableArray):

  localOverlays = [NSKeyedUnarchiver unarchiveObjectWithData: data];

将此行替换为:

  localOverlays = [[NSKeyedUnarchiver unarchiveObjectWithData: data] mutableCopy];

我希望有所帮助!

答案 1 :(得分:0)

我已经解决了这个问题!我来实现,坐标两个变量,纬度和经度都是双打,数据类型...... NOT对象!因此,他们坚持并且只是工作,因为他们被复制......不像参考的对象。长话短说我需要retain。就像这样:

        title = [[aDecoder decodeObjectForKey: @"titler"] retain];
        subtitle = [[aDecoder decodeObjectForKey: @"subtitler"] retain];