【问题标题】:How to trigger MKAnnotationView's callout view without touching the pin?如何在不触摸引脚的情况下触发 MKAnnotationView 的标注视图?
【发布时间】:2009-06-11 01:30:11
【问题描述】:

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

我该怎么做?在 annotationview 上调用 setSelected:YES 什么也没做。我正在考虑模拟针上的触摸,但我不知道该怎么做。

【问题讨论】:

标签: iphone


【解决方案1】:

但是要让 benvolioT 的解决方案起作用,代码有一个问题

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

应该从- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView 调用,而不是其他地方。

在第一次加载特定位置的地图和随后的地图加载时,调用各种方法(如UIViewControllerviewWillAppearviewDidAppear- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView)的顺序不同显示在同一位置。这有点棘手。

【讨论】:

  • 没什么棘手的。只需要知道调用:[mapView selectAnnotation] 而不是 [annotation setSelected]。谢谢!
  • 好的,这是第一次自动工作。但现在它不再工作了?什么? - (void)mapViewDidFinishLoadingMap:(MKMapView *)_mapView { [mapView selectAnnotation:addAnnotation animated:YES]; }
  • mapViewDidFinishLoadingMap 仅在地图缓存时第一次触发。从缓存加载地图时,不再触发 mapViewDidFinishloadingMap。
  • 确保注释视图已准备好显示标注的正确委托方法是@user507778 指出的方法。 mapView:didAddAnnotationViews:。这确保了地图视图已加载,并且注释视图已放置并准备好显示标注气泡。任何其他方式都可以工作与否,取决于连接速度、缓存系统、应用程序中断等。
  • @LeandroAlves 这是正确的解决方案。谢谢你。出于与您描述的相同的原因,否决了根本答案。
【解决方案2】:

好的,这就是这个问题的解决方案。

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

【讨论】:

  • 这没有帮助。我可以调用它,它不会总是为选择设置动画。第一次,是的。此后每次都不会 - 即使调用了该方法。 benvolioT 的解决方案也对我不起作用。即使我直接调用 selectAnnotation:animated: ,当注释已知时,也不起作用。和以前一样的问题。 :(
  • @Joe 我相信您必须在调用之前删除注释才能显示动画。
  • 评论说如果 pin 处于 selected 状态,并且您再次选择它,它仍然处于相同的 selected 状态。直到您取消选择它或用户取消选择它。
【解决方案3】:

假设你想选择最后一个注解视图,你可以把代码放在下面:

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

在下面的委托中:

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

【讨论】:

  • 这将是对我有用的解决方案!非常感谢!
  • 小心!为当前可见的注释调用此委托方法,即当前显示在屏幕上的地图区域内的注释。
【解决方案4】:

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

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

【讨论】:

  • 我发现这是最好的方法,因为添加注释时会触发此方法。
  • 这个方法把标注和图钉一起丢掉,有没有办法可以在图钉掉到地图后立即显示标注?
【解决方案5】:

在尝试了这个帖子的各种答案后,我终于想出了这个。它工作得非常可靠,我还没有看到它失败:

- (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];
            });
        }
    }
}

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

【讨论】:

  • 难以置信。它是如此的混乱,它处于竞争状态,但它确实有效。这里令人震惊的是,故事板几乎可以做所有事情,如果您在 3 个月内没有接触过 MKMapViews,则代理需要通过故事板连接起来并不明显。这是故事板应该自动完成的事情,或者至少警告你。我宁愿在 init 上定义 mapKit ref 和在 init 上定义委托,也不愿让情节提要完成 1/2 的工作,让你在不知道还有 1/2 的工作要做的情况下挂起。 >为此浪费了 1 小时。
  • 这非常适合在完成图钉放置后立即显示标注。没有延迟,您会看到标注与图钉一起掉落,这看起来很奇怪。不幸的是,“didAddAnnotationViews”在 pin 开始下降的那一刻被调用,而不是在它落地的那一刻。
【解决方案6】:

这对我不起作用。我怀疑 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];
    }
}

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

【讨论】:

  • 基于此我得到 [mapView selectAnnotation:[mapView.annotations objectAtIndex:0] animated:false];努力挑选第一个注释。
【解决方案7】:

如果你只是想打开你添加的最后一个注释的标注,试试这个,对我有用。

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

【讨论】:

    【解决方案8】:

    - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView 调用selectAnnotation 的问题在于,顾名思义,此事件仅在您的 MapView 初始加载时触发,因此如果您在之后添加注解,您将无法触发注解的标注MapView 已完成加载。

    - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views 调用它的问题是,当调用selectAnnotation 时,您的注释可能不在屏幕上,这将导致它不起作用。即使您在添加注释之前将 MapView 的区域居中到注释的坐标,设置 MapView 区域所需的轻微延迟也足以在屏幕上显示注释之前调用 selectAnnotation,特别是如果您为 @987654326 设置动画@。

    有些人通过在延迟后致电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 的区域设置为注释的坐标),因为此事件是在 @ 之后触发的987654330@(及其动画)已完成。然而,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)someMethod 中的区域设置之外没有任何区域设置会触发标注。

    【讨论】:

      【解决方案9】:

      我仔细阅读了API,终于发现了问题:


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

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

      【讨论】:

      • 这是在创造竞争条件。是不是有一个事件表明地图已经显示完毕,可以用来触发显示?
      【解决方案10】:

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

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

      例如:首先,我需要在 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检测方法,现阶段自己尝试这样做有点不必要。

      【讨论】:

        【解决方案11】:

        Steve Shi 的回复让我清楚地知道 selectAnnotation 必须从 mapViewDidFinishLoadingMap 方法中调用。不幸的是,我不能投票,但我想在这里说声谢谢。

        【讨论】:

          【解决方案12】:

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

          【讨论】:

            【解决方案13】:

            重置注释也会将标注放在前面。

                [mapView removeAnnotation: currentMarker];
                [mapView addAnnotation:currentMarker];
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-06
              • 2013-06-02
              • 1970-01-01
              • 1970-01-01
              • 2017-04-21
              • 1970-01-01
              相关资源
              最近更新 更多