【问题标题】:Add annotations from map into a NSMutableArray将地图中的注释添加到 NSMutableArray
【发布时间】:2014-03-03 19:00:35
【问题描述】:

我有一张地图,我可以在上面添加多个带有可自定义字幕的注释。我想将注释放入带有更新字幕的数组中。

目前,当我添加注释时,它会进入数组,但我不知道如何使用字幕更新数组,如果注释从地图中删除,则从数组中删除注释。

我还想在切换到下一个视图时将所有注释添加到数组中,但不知道该怎么做。

我当前的代码:

使用 UIGestureRecognizer 添加注释

    MapAnnotation *mapPoint = [[MapAnnotation alloc]init];

    mapPoint.coordinate = touchMapCoordinate;
    mapPoint.title = address;
    mapPoint.subtitle = @"";

    [self.map addAnnotation:mapPoint];

    self.mapLatitudeString = [NSString stringWithFormat:@"%f",mapPoint.coordinate.latitude];
    self.mapLongitudeString = [NSString stringWithFormat:@"%f",mapPoint.coordinate.longitude];
    self.mapTitleString = [NSString stringWithFormat:@"%@", mapPoint.title];
    self.mapSubtitleString = [NSString stringWithFormat:@"%@", mapPoint.subtitle];

    self.mapAnnotation = [NSString stringWithFormat:@"%d,%@,%@,%@,%@",self.mapAnnotationArray.count, self.mapLatitudeString, self.mapLongitudeString, self.mapTitleString, self.mapSubtitleString];

    if (!self.mapAnnotationArray) {
        self.mapAnnotationArray = [[NSMutableArray alloc] init];
    }
    [self.mapAnnotationArray addObject:self.mapAnnotation];
    NSLog(@"%@", self.mapAnnotationArray);

编辑字幕并从警报视图中删除注释

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0) {
    }
    if (buttonIndex == 1) {
        if (self.map.selectedAnnotations.count > 0)
        {
            id<MKAnnotation> ann = [self.map.selectedAnnotations objectAtIndex:0];

            if ([ann isKindOfClass:[MapAnnotation class]])
            {
                MKPointAnnotation *pa = (MKPointAnnotation *)ann;
                pa.subtitle = [[alertView textFieldAtIndex:0] text];
            }
        }
    }
    if (buttonIndex == 2) {
        [self.map removeAnnotations:self.map.selectedAnnotations];
    }
}

【问题讨论】:

  • mapAnnotationArray 是做什么用的?如果您将 mapPoint 注释对象本身而不是 self.mapAnnotation 字符串添加到数组中,将会简单得多。
  • @Anna 我将把mapAnnotationArray 传递到一个MySQL 数据库中,稍后我可以从中检索,带有标题和副标题的经纬度坐标,并将注释绘制到另一个地图视图上,mapPoint 不是t 像 NSString 那样向我展示完整的细节。
  • 您要将注释数据作为逗号分隔的字符串存储在数据库中吗?不建议这样做。尽管如此,当您将数据保存在数组中时,您不需要将其存储为格式化字符串。您可以在 MapAnnotation 类中添加一个 description 方法覆盖,该类根据该类的不同属性按需输出格式化的字符串。通过将数据存储为分隔字符串,您必须不断解析它以检索和搜索值。
  • 一个单独的潜在问题是注释编号方案:如果删除了注释,那么以后添加的新注释可以获得与已删除或现有注释相同的编号,从而导致冲突/重复。在继续之前,您可能需要重新考虑整体设计/方法。
  • @Anna 我通过 php 将数组发送到数据库,php 文件会删除任何不需要的字符并存储要检索的字符串并使用我使用的代码放置到地图上,目前这正在工作。我对此只有两个问题,如果我向数组添加注释,我无法将其删除,也无法将编辑后的字幕添加到数组中。我确实理解您提到的方式更适合使用,特别是如果它可以帮助我解决这两个问题,但我不知道如何实现。

标签: ios nsmutablearray mkmapview mkannotation


【解决方案1】:

使用当前将每个注释的格式化字符串表示(包括序列号)添加到mapAnnotationArray 的方法,维护数组的过程很繁琐:

  1. 要更新其中一个格式化字符串中的字段,您必须:
    一种。循环遍历数组,
    湾。解析字符串(例如使用componentsSeparatedByString),
    C。检查字段是否与您要查找的注释匹配,
    d。使用新值重建格式化字符串,
    e.使用replaceObjectAtIndex:withObject: 更新数组中的字符串
  2. 要从数组中删除一个条目,您必须:
    一种。执行与 1a 到 1c 相同的步骤,
    湾。使用removeObjectAtIndex:删除字符串
    C。更新所有剩余注释中的注释序列号

每次您要检索或搜索mapAnnotationArray 中的字段时,都必须执行这些步骤。它既不高效也不灵活(如果用户决定在字幕中使用逗号,如果地址包含逗号等怎么办)。


相反,将注释对象本身存储在mapAnnotationArray 中,并且仅在需要将数据提交到服务器时生成格式化的字符串表示。在数组中存储适当的对象可以让您利用面向对象的方法。

  1. 在将注解添加到地图的方法中,不是将格式化字符串添加到mapAnnotationArray,而是添加注解本身:

    [self.mapAnnotationArray addObject:mapPoint];
    
  2. 在警报视图委托方法中更新注解的subtitle 时,您现在不需要对mapAnnotationArray 执行任何操作,因为数组中的注解对象是确切与您更新 subtitle 的对象相同。您可以在此处 NSLog 数组以查看更改。

  3. 在警报视图委托方法中删除注释的地方,您需要从mapAnnotationArray 中删除相同的对象(地图视图不知道您的数组):

    if (buttonIndex == 2) 
    {
        if (self.map.selectedAnnotations.count > 0)
        {
            id<MKAnnotation> ann = [self.map.selectedAnnotations objectAtIndex:0];
            if ([ann isKindOfClass:[MapAnnotation class]])
            {
                [self.mapAnnotationArray removeObject:ann];
            }
            [self.map removeAnnotations:self.map.selectedAnnotations];
        }
    }
    
  4. 接下来,为了更轻松地生成格式化字符串和调试mapAnnotationArray 的内容,将description 方法的辅助方法和覆盖添加到MapAnnotation 类中:

    -(NSString *)stringForServer
    //You can name this method whatever you want.
    //Builds the comma-delimited representation 
    //of this annotation (excluding the sequence number).
    //Note this format still "breaks" if title or subtitle contain commas.
    {
        NSString *result = [NSString stringWithFormat:@"%f,%f,%@,%@",
                            self.coordinate.latitude, 
                            self.coordinate.longitude, 
                            self.title, 
                            self.subtitle];
        return result;
    }
    
    -(NSString *)description
    //This method must be named this.
    //When you NSLog this object, it will call this method to get
    //what string to display for it.
    {
        return [NSString stringWithFormat:@"%@ (%@)", 
                   [super description], [self stringForServer]];
    }
    
  5. 最后,无论您将数据提交到服务器的何处,循环遍历数组并从注释对象生成格式化字符串(并在序列号前加上前缀)。这个例子只是循环遍历数组和 NSLogs 每个注释的格式化字符串:

    for (int i=0; i < self.mapAnnotationArray.count; i++)
    {
        MapAnnotation *ma = (MapAnnotation *)[self.mapAnnotationArray objectAtIndex:i];
        NSString *maString = [ma stringForServer];
        NSString *fullStringForServer = [NSString stringWithFormat:@"%d,%@", i, maString];
        NSLog(@"maa[%d] = %@", i, fullStringForServer);
    }
    

    在您实际准备好保存数据时为序列号添加前缀可避免重新编号和重复问题。当然,这假设注释不必在保存时保持相同的序列号。

    还可以考虑使用 JSON 而不是逗号分隔的格式。 NSJSONSerialization 使它相对容易。示例见Convert an iOS objective c object to a JSON string

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多