注释地图标题标题显示错误

时间:2014-07-31 17:32:36

标签: ios objective-c ios7 mkmapview mkannotationview

注释引脚标题显示所有引脚的相同标题。我已设置标签以显示每个引脚的标题,但我获得所有标签的相同标题。我做了NSLog lbl.text和NSLog中显示不同的标题。

为什么我为所有地图引脚获得相同的标题。

    -(void)maprequests
    {

    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    // getting an NSString
    NSString *emailid = [prefs stringForKey:@"email"];
    NSString *deviceid = [Request UDID];
    //NSString * walkGUID=[prefs stringForKey:@"walkguid"];
    //NSLog(@"walkGUID:%@",walkGUID);
    NSString * walkguid=[prefs stringForKey:@"walkguid"];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://10.0.0.28/web/ws/get_poilist_walks.php?strEmailID=%@&strDeviceID=%@&strWalkGuid=%@",emailid,deviceid,walkguid]];

    NSLog(@"%@",url);

    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //AFNetworking asynchronous url request
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    operation.responseSerializer = [AFJSONResponseSerializer serializer];
    operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        self.pointofintrests = [responseObject objectForKey:@"PointOfIntrests"];
                NSIndexPath *indexpath;

        NSDictionary *tempDictionary= [self.pointofintrests objectAtIndex:indexpath.row];

        for (NSDictionary *dictionary in _pointofintrests)
        {
            MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
            NSString * latitude= [dictionary objectForKey:@"Latitude"];
            NSString * longitude =[dictionary objectForKey:@"Longitude"];
            double strlatitude = [latitude doubleValue];
            double strlongitude = [longitude doubleValue];
            region.center.latitude =strlatitude;
            region.center.longitude =  strlongitude;
            region.span.longitudeDelta = 0.01f;
            region.span.latitudeDelta = 0.01f;
            [_mapview setRegion:region animated:YES];
            [_mapview setDelegate:self];

            DisplayMap *ann = [[DisplayMap alloc] init];
            ann.coordinate = region.center;

            [_mapview addAnnotation:ann];

        }

    }
     failure:^(AFHTTPRequestOperation *operation, NSError *error)
     {
        NSLog(@"Request Failed: %@, %@", error, error.userInfo);

    }];

    [operation start];



}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{

    MKPinAnnotationView *pinView = nil;
    UILabel *label;
    if(annotation != mapView.userLocation)
    {

        static NSString *defaultPinID = @"com.invasivecode.pin";
        pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
        if ( pinView == nil ) pinView = [[MKPinAnnotationView alloc]
                                         initWithAnnotation:annotation reuseIdentifier:defaultPinID];

        if(![annotation isKindOfClass:[DisplayMap class]])
            return nil;

        DisplayMap *a = (DisplayMap *)annotation;
        pinView.image=[UIImage imageNamed:@"push_pin@2x"];


        UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 250, 30)];
        lbl.backgroundColor = [UIColor clearColor];
        lbl.textColor = [UIColor whiteColor];
        lbl.alpha = 0.5;
        lbl.tag = 42;
        for (int i=0; i<_pointofintrests.count; i++)
        {
        lbl.text = [[_pointofintrests valueForKey:@"title"] objectAtIndex:i];
        }
        [pinView addSubview:lbl];

        [_mapview selectAnnotation:pinView animated:YES];

        pinView.canShowCallout = YES;
        pinView.animatesDrop = NO;

    }
    else
    {


    }


     return pinView;

   }

2 个答案:

答案 0 :(得分:0)

您的问题是您正在循环_pointofinterests

for (int i=0; i<_pointofintrests.count; i++)
{
    lbl.text = [[_pointofintrests valueForKey:@"title"] objectAtIndex:i];
}

这不符合你的想法。它将数组中的最后一个标题分配给每个引脚。

因为viewForAnnotation委托方法为您提供了将要显示的注释,我倾向于保留一组注释来保存索引,因此您可以正确访问数据。

当您致电[_mapview addAnnotation:ann];时,也会将ann保存到数组中。

然后你应该能够做出类似的事情:

[[_pointofintrests valueForKey:@"title"] objectAtIndex:[annArray indexOfObject:annotation]]

作为旁注,如果_pointofinterestsNSDictionary,我会改用objectForKey

答案 1 :(得分:0)

正如在另一个答案中已经指出的那样,在所有引脚上获得相同标签文本的主要原因是,对于每个引脚,lbl.text始终设置为{{1}中最后一个对象的标题}}

我更喜欢的解决方案是设置注释_pointofintrests并使用它来设置标签的文本。

  1. 创建注释时,在调用title之前,请设置其addAnnotation属性:

    title
  2. DisplayMap *ann = [[DisplayMap alloc] init]; ann.coordinate = region.center; ann.title = [dictionary objectForKey:@"title"]; //<-- add this line [_mapview addAnnotation:ann]; 中,您可以简单地将标签的文本设置为注释的标题(不搜索数组或循环),而不是viewForAnnotation循环:

    for

  3. 这在技术上解决了所有引脚上出现相同文本的问题。

    但是,//for (int i=0; i<_pointofintrests.count; i++) //{ // lbl.text = [[_pointofintrests valueForKey:@"title"] objectAtIndex:i]; //} lbl.text = annotation.title; 中的代码还存在其他一些问题,这些问题在上述修复后会变得明显:

    • 即使注释视图已出列(意味着正在重新使用先前创建的视图),viewForAnnotation也会添加到注释视图中。该出列的视图已经其中包含UILabel,现有代码将在顶部添加另一个。平移和缩放地图一段时间后,您会注意到每个图钉的重叠标签。

      UILabel只应在创建新视图时添加(当出列队列返回UILabel而你nil + alloc新的视图时)。

    • 另一个问题是,由于您使用自定义图片作为注释,因此应创建普通init而不是MKAnnotationViewMKPinAnnotationView类用于显示标准的内置图钉图像,虽然它仍具有MKPinAnnotationView属性,但有时会忽略它并恢复显示其标准图钉图像。

    • 另一个问题是这一行:

      image
      • 地图视图一次只能有一个“选中”注释,所以如果你认为在[_mapview selectAnnotation:pinView animated:YES]; 中调用它会同时显示所有注释的标注,那就错了。
      • viewForAnnotation方法需要注释作为第一个参数。 selectAnnotation不是注释 - 它是注释的视图(它们不是同一个东西)。编译器必须抱怨此行,并且在运行时,系统可能在控制台中显示错误,例如“尝试选择尚未添加的注释”。从技术上讲,该行应为pinView
      • 无论如何,请勿在{{1​​}}委托方法中调用[_mapview selectAnnotation:annotation animated:YES];这样做可能会导致递归和堆栈溢出(以及EXC_BAD_ACCESS),因为select会导致要更新的注释视图会导致调用viewForAnnotation等。而是在selectAnnotation委托方法中为要显示标注的 one 注释调用它。

    您修改后的viewForAnnotation委托方法可能如下所示:

    didAddAnnotationViews

    请记住,您还需要设置注释的viewForAnnotation,如答案顶部所示。


    我想指出-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if(! [annotation isKindOfClass:[DisplayMap class]]) { return nil; } static NSString *defaultPinID = @"MyPin"; int lblTag = 42; MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID]; if (pinView == nil) { pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID]; pinView.image = [UIImage imageNamed:@"push_pin@2x"]; pinView.canShowCallout = YES; //Create and add the label to the view ONCE when creating the view... UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 250, 30)]; lbl.backgroundColor = [UIColor clearColor]; lbl.textColor = [UIColor whiteColor]; lbl.alpha = 0.5; lbl.tag = lblTag; [pinView addSubview:lbl]; } else { //If we are re-using a dequeued view //update its annotation reference... //(otherwise view will still be pointing to its previous annotation) pinView.annotation = annotation; } //At this point, we have a new or dequeued view //pointing to the current annotation. //Now update the label that will already be there //with the current annotation's title... UILabel *lbl = (UILabel *)[pinView viewWithTag:lblTag]; lbl.text = annotation.title; return pinView; } 方法中的title循环中还有一些内容:

    • 没有必要创建和设置区域只是为了设置注释的坐标。在循环中调用for是没有意义且效率低的,因为用户最终只会看到位于最后一个注释的地图。要设置注释坐标,只需执行:

      maprequests
    • 您可以在 setRegion循环之后致电ann.coordinate = CLLocationCoordinate2DMake(strlatitude, strlongitude); (一次)(或只需致电setRegion,这样您就无需自行计算显示所有注释的区域。

    • 您无需反复在for循环内设置地图视图的[_mapview showAnnotations:_mapview.annotations animated:YES];。在 delegate循环之前设置for(一次)(尽管在调用此方法之前应该已经设置了很久)。