如何在不触摸图钉的情况下触发MKAnnotationView的标注视图?


75

我正在MKMapView使用通常的彩色图钉作为定位点。我希望能够在不触摸图钉的情况下显示标注。

我该怎么办?调用setSelected:YES注释视图没有任何作用。我正在考虑模拟在别针上的触摸,但是我不确定该怎么做。


我在其他问题中的解决方案:stackoverflow.com/a/13026353/736384
Luis Ascorbe 2012年

Answers:


63

但是有一个问题可以使benvolioT的解决方案起作用,代码

for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
    if ([currentAnnotation isEqual:annotationToSelect]) {
        [mapView selectAnnotation:currentAnnotation animated:FALSE];
    }
}

应该从调用- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView,而在其他任何地方都不能调用。

的序列,其中的各种方法喜欢viewWillAppearviewDidAppearUIViewController并且- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView被称为是第一次地图被加载有一个特定的位置和后续次地图被显示以相同的位置之间不同。这有点棘手。


4
没什么棘手的。只需知道要调用:[mapView selectAnnotation]而不是[annotation setSelected]。谢谢!
特福德

好的,这是第一次自动进行。但是现在它不工作了吗?什么 -(void)mapViewDidFinishLoadingMap:(MKMapView *)_ mapView {[mapView selectAnnotation:addAnnotation animation:YES]; }
fulvio 2010年

4
mapViewDidFinishLoadingMap仅在缓存地图时才首次触发。从缓存加载地图后,不再触发mapViewDidFinishloadingMap。
Niels R.

8
确保您的注释视图已准备好显示标注的正确委托方法是@ user507778指出的方法。mapView:didAddAnnotationViews:。这样可以确保地图视图已加载,注释视图也已放置并准备显示标注气泡。取决于连接速度,缓存系统,应用程序中断等,任何其他方式都行不通。
Leandro Alves 2012年

1
@LeandroAlves这是正确的解决方案。谢谢。出于与您描述的完全相同的原因而拒绝了基本答案。
Aleks N. 2012年

34

好的,这是解决此问题的方法。

要显示标注,请使用MKMapViewselectAnnotation:animated方法。


3
这没有帮助。我可以称呼它,但它并不总是使选择动画。第一次,是的。每次之后,即使调用该方法也不会。benvolioT的解决方案对我也不起作用。即使我直接调用selectAnnotation:animated:,当知道注释时,也无法正常工作。与以前一样的问题。:(
乔D'安德里亚

@Joe我相信您必须在重新调用之前删除注释才能显示动画。
丹尼·男孩

指出如果引脚处于选定状态,然后再次选择它,它将保持相同的选定状态。直到您取消选择它或用户取消选择它。
dklt 2012年

32

假设您要选择最后一个注释视图,可以将代码放在下面:

[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];

在下面的代表中:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
    //Here
    [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
}

这将是对我有用的解决方案!非常感谢!
Toran Billups

1
小心!对于当前可见的注释(即那些当前显示在屏幕上的地图区域内的注释),将调用此委托方法。
路易斯·阿斯科贝

21

好的,要成功添加标注,您需要使用委托人的didAddAnnotationViews在添加所有注释视图之后调用selectAnnotation:animated:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
    for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
        if ([currentAnnotation isEqual: annotationToSelect]) {
            [mapView selectAnnotation:currentAnnotation animated:YES];
        }
    }
}

我发现这是最好的方法,因为添加注释时将触发此方法。
加文

1
此方法将标注与图钉一起丢弃,是否有解决方案可以在将图钉放置到地图后立即显示标注?
迈克尔

12

在对该线程尝试了各种答案之后,我终于想到了这一点。它工作非常可靠,我还没有看到它失败:

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views;
{
    for(id<MKAnnotation> currentAnnotation in aMapView.annotations) 
    {       
        if([currentAnnotation isEqual:annotationToSelect]) 
        {
            NSLog(@"Yay!");
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^
            {
                [aMapView selectAnnotation:currentAnnotation animated:YES];
            });
        }
    }
}

该块用于稍微延迟,因为没有它,标注可能无法正确显示。


2
难以置信的。这太过分了,而且处于比赛状态,但确实有效。令人震惊的是,由于故事板几乎可以完成所有事情,因此委托人不需要通过故事板进行连接就很明显-如果您三个月没有触摸MKMapViews。这是情节提要板应该自动执行的操作,或至少会警告您。我宁愿在init上定义mapKit ref,在init上定义委托,而不是让情节提要板完成1/2的工作并使您挂起,而又不知道还有1/2的工作要做。在此上浪费了> 1个小时。
Alex Zavatone 2012年

这样非常有用,可以在图钉插入操作完成后立即显示标注。在没有延迟的情况下,您会看到标注随引脚而下降,这看起来很奇怪。不幸的是,“ didAddAnnotationViews”是在引脚开始掉落的时候而不是在着陆的时候被调用的。
James Toomey

9

这对我不起作用。我怀疑MapKit API中存在错误。

请参阅此链接,以了解无法使用此功能的其他用户的详细信息:http : //www.iphonedevsdk.com/forum/iphone-sdk-development/19740-trigger-mkannotationview-callout-bubble.html#post110447

- 编辑 -

好了,花了一段时间后,这才是我能够做的工作:

for (id<MKAnnotation> currentAnnotation in mapView.annotations) {       
    if ([currentAnnotation isEqual:annotationToSelect]) {
        [mapView selectAnnotation:currentAnnotation animated:FALSE];
    }
}

请注意,这需要- (BOOL)isEqual:(id)anObject为您的实现MKAnnotation协议的类实现。


基于此,我得到了[mapView selectAnnotation:[mapView.annotations objectAtIndex:0] animation:false]; 工作以选择第一个注释。
2009年

6

如果您只想打开添加的最后一个注释的标注,请尝试使用此方法,它对我有用。

[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];


6

顾名思义,调用selectAnnotationfrom的问题- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView是,此事件仅在MapView最初加载后才触发,因此,如果在MapView完成加载后添加注释,则无法触发该注释。

从中调用- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views注释的问题是,调用注释时,注释可能不在屏幕上,selectAnnotation这将导致注释无效。即使在添加注释之前将MapView的区域居中到注释的坐标处,设置MapView的区域所花费的轻微延迟也足以selectAnnotation在注释在屏幕上可见之前被调用,特别是如果设置了动画setRegion

有些人通过selectAnnotation在这样的延迟后致电来解决此问题:

-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
    [self performSelector:@selector(selectLastAnnotation)
        withObject:nil afterDelay:1];
}

-(void)selectLastAnnotation {
    [myMapView selectAnnotation:
        [[myMapView annotations] lastObject] animated:YES];
}

但是即使那样,您也可能会得到奇怪的结果,因为注释可能要花费一秒钟以上的时间才能显示在屏幕上,具体取决于各种因素,例如以前的MapView区域与新区域之间的距离或Internet连接速度。

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated之所以决定进行调用,是因为它可以确保注释实际上在屏幕上(假设您将MapView的区域设置为注释的坐标),因为此事件是 setRegion(及其动画)完成之后触发的。但是,regionDidChangeAnimated只要您的MapView的区域发生变化(包括用户仅在地图上平移时),就会触发,因此您必须确保您有条件正确识别何时才是触发注释的标注的正确时间。

这是我的做法:

MKPointAnnotation *myAnnotationWithCallout;

- (void)someMethod {
    MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
    [myAnnotation setCoordinate: someCoordinate];
    [myAnnotation setTitle: someTitle];

    MKCoordinateRegion someRegion =
       MKCoordinateRegionMakeWithDistance (someCoordinate, zoomLevel, zoomLevel);

    myAnnotationWithCallout = myAnnotation;
    [myMapView setRegion: someRegion animated: YES];
    [myMapView addAnnotation: myAnnotation];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if (myAnnotationWithCallout)
    {
        [mapView selectAnnotation: myAnnotationWithCallout animated:YES];
        myAnnotationWithCallout = nil;
    }
}

这样一来,您的注解就可以在当前selectAnnotation被显示在屏幕上,并且该if (myAnnotationWithCallout)部件确保除- (void)someMethodinone外的其他任何区域设置都不会触发标注。


5

我仔细阅读了API,最后发现了问题:


如果指定的注释不在屏幕上,因此没有关联的注释视图,则此方法无效。

因此,您可以等待一段时间(例如3秒),然后执行此操作。然后就可以了。


1
这创造了竞争条件。是否没有事件指示地图已完成显示,您可以用来触发显示?
Alex Zavatone 2012年

3

由于类似于benvolioT所示的代码,我怀疑系统中存在该代码,因此当我使用selectAnnotation:animation:方法时,它没有显示callOut,我猜测原因是因为它已被选择并且正在避免要求MapView使用注释标题和副标题在地图上重新绘制标注。

因此,解决方案就是先取消选择它,然后重新选择它。

例如:首先,我需要在Apple的touchMoved方法中执行此操作(即,如何拖动AnnotationView)以隐藏callOut。(仅使用annotation.canShowAnnotation = NO不能正常工作,因为我怀疑它需要重绘。deselectAnnotaiton会导致必要的操作。此外,仅取消选择并不能解决问题,callOut仅消失一次并立即被重画。这提示它已自动重新选择)。

annotationView.canShowAnnotation = NO;
[mapView deselectAnnotation:annotation animated:YES];

然后,仅在touchEnded方法中使用下面的代码并没有带回callOut(此时注释已由系统自动选择,并且可能永远不会重绘callOut):

annotationView.canShowAnnotation = YES;
[mapView selectAnnotation:annotation animated:YES];

解决方案是:

annotationView.canShowAnnotation = YES;
[mapView deselectAnnotation:annotation animated:YES];
[mapView selectAnnotation:annotation animated:YES];

这只是回购了callOut,大概是重新启动了mapView重绘callOut的过程。

严格来说,我应该检测注释是否为当前注释(选中,我知道是),以及callOut是否实际显示(我不知道),并决定相应地重绘它,这样会更好。但是,我还没有找到callOut检测方法,因此我自己在这个阶段就没有必要了。


1

史蒂夫·史(Steve Shi)的回应清楚地表明,必须从mapViewDidFinishLoadingMap方法调用selectAnnotation。不幸的是我不能投票,但我想在这里说谢谢。


0

只需添加[mapView selectAnnotation:point animation:YES];


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.