以编程方式更改MKAnnotationView

时间:2012-09-04 13:45:59

标签: objective-c mkannotationview

有没有办法改变MKAnnotationView样式(例如从带有数字的红色标签到带有数字的绿色标签)。

我想根据与目标的距离来改变这种风格。我的注释正在与用户一起移动。

我不想使用删除/添加注释,因为它会导致“闪烁”。 可以这样做吗?

更新

我正在添加代码,我现在正在做什么

MKAnnotationView *av = [mapView viewForAnnotation:an];

if ([data->type isMemberOfClass:[UserAnnotationImage class]])
{
    UIImage *img = [UIImage imageNamed: ((UserAnnotationImage *)data->type)->url];
    [av setImage:img];
}
else if ([data->type isMemberOfClass:[UserAnnotationLabel class]])
{

    UIView * v = [av viewWithTag:0];
    v = ((UserAnnotationLabel *)data->type)->lbl;

    av.frame = ((UserAnnotationLabel *)data->type)->lbl.frame;
}
else if ([data->type isMemberOfClass:[UserAnnotationView class]])
{

    UIView * v = [av viewWithTag:0];
    v = ((UserAnnotationView *)data->type)->view;
    av.frame = ((UserAnnotationView *)data->type)->view.frame;
}

可悲的是,它不起作用:(

1 个答案:

答案 0 :(得分:4)

是的,基本上您可以获得对注释视图的引用并直接更新其内容。

另一种方法是,如果你有一个自定义注释视图类,那就是让注释视图监视它感兴趣的更改(或者在外面告诉它)并更新自己。

如果您使用普通MKAnnotationViewMKPinAnnotationView,第一种方法会更简单。

无论您何时检测到需要对视图进行更改,都可以通过调用地图视图的viewForAnnotation 实例方法来获取对视图的引用。这与调用viewForAnnotation委托方法不同。

获得对视图的引用后,您可以根据需要进行修改,并且应立即显示更改。

重要的一点是,用于更新委托方法之外的视图的逻辑以及viewForAnnotation委托方法中的逻辑必须匹配。这是因为地图视图可能稍后调用委托方法(在您手动更新视图之后),并且当它执行时,其中的代码应该考虑更新的数据。

最好的方法是将注释视图构造代码放在一个通过委托方法调用的公共方法中,并手动更新视图。

有关仅更新注释视图image的示例,请参阅change UIImage from MKAnnotation in the MKMapView

对于使用自定义注释视图类更新视图的示例(主要是方法的想法),请参阅iPad Mapkit - Change title of "Current Location"定期更新视图的引脚颜色(绿色,紫色,红色,绿色,紫色,红色等。)

<小时/> 您的代码中有太多未知数来解释它为什么不起作用。例如:

  • 什么是data?它是注释特定的(它与an有关)吗?什么是type?注释添加到地图后是否会更改?
  • 为什么data存储整个视图对象,例如UILabelUIView,而不仅仅是您希望在这些视图中显示的基础数据?
  • imageNamed要求图片是项目中的资源(不是任意网址)
  • 请勿使用0的标记(这是所有视图的默认标记)。从1开始编号。
  • 您使用viewWithTag获取视图,然后立即将其替换为另一个视图。


我会提供一个更详细但更简单的(r)示例 ...

假设您有一个具有这些属性的注释类(实现MKAnnotation的类)(除了坐标,标题和副标题):

@property (nonatomic, assign) BOOL haveImage;
@property (nonatomic, copy) NSString *labelText;
@property (nonatomic, copy) NSString *imageName;
@property (nonatomic, assign) CLLocationDistance distanceFromTarget;

为了解决上面提到的“重点”(viewForAnnotation委托方法和视图更新代码应该使用相同的逻辑),我们将创建一个传递注释视图和配置的方法它根据需要基于注释的属性。然后,viewForAnnotation委托方法和注释属性更改时手动更新视图的代码将调用此方法。

在此示例中,我进行了操作,以便注释视图显示haveImageYES时的图像,否则显示标签。此外,标签的背景颜色基于distanceFromTarget

-(void)configureAnnotationView:(MKAnnotationView *)av
{
    MyAnnotationClass *myAnn = (MyAnnotationClass *)av.annotation;

    UILabel *labelView = (UILabel *)[av viewWithTag:1];

    if (myAnn.haveImage)
    {
        //show image and remove label...
        av.image = [UIImage imageNamed:myAnn.imageName];
        [labelView removeFromSuperview];
    }
    else
    {
        //remove image and show label...
        av.image = nil;

        if (labelView == nil)
        {
            //create and add label...
            labelView = [[[UILabel alloc] 
                initWithFrame:CGRectMake(0, 0, 50, 30)] autorelease];
            labelView.tag = 1;
            labelView.textColor = [UIColor whiteColor];
            [av addSubview:labelView];
        }

        if (myAnn.distanceFromTarget > 100)
            labelView.backgroundColor = [UIColor redColor];
        else
            labelView.backgroundColor = [UIColor greenColor];

        labelView.text = myAnn.labelText;
    }
}

viewForAnnotation委托方法如下所示:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 
{
    if ([annotation isKindOfClass:[MyAnnotationClass class]])
    {
        static NSString *myAnnId = @"myann";
        MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:myAnnId];
        if (av == nil)
        {
            av = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:myAnnId] autorelease];
        }
        else
        {
            av.annotation = annotation;
        }

        [self configureAnnotationView:av];

        return av;
    }

    return nil;
}

最后,注释属性发生变化的位置以及要更新注释视图的位置,代码看起来像这样:

ann.coordinate = someNewCoordinate;
ann.distanceFromTarget = theDistanceFromTarget;
ann.labelText = someNewText;
ann.haveImage = YES or NO;
ann.imageName = someImageName;

MKAnnotationView *av = [mapView viewForAnnotation:ann];
[self configureAnnotationView:av];