【问题标题】:Wanted: How to reliably, consistently select an MKMapView annotation通缉:如何可靠、一致地选择 MKMapView 注释
【发布时间】:2010-11-18 10:01:10
【问题描述】:

在调用MKMapViewsetCenterCoordinate:animated:方法(没有动画)之后,我想调用selectAnnotation:animated:(带动画),以便注释从新居中的图钉中弹出。

现在,我只是观察 mapViewDidFinishLoadingMap:,然后选择注释。然而,这是有问题的。例如,当不需要加载额外的地图数据时,不会调用此方法。在这些情况下,我的注释未被选中。 :(

很好。我可以在设置中心坐标后立即调用它。啊,但在这种情况下,可能会有 地图数据要加载(但它还没有完成加载)。我会冒着过早调用它的风险,因为动画充其量会变得参差不齐。

因此,如果我理解正确,则不必知道我的坐标是否可见,因为它可能会偏离几乎一屏的距离并且必须加载新的地图数据。相反,这是一个知道是否需要加载新的地图数据,然后采取相应措施的问题。

关于如何实现这一点,或者在将地图视图重新居中于注释所在的坐标上之后如何(可靠地)选择注释的任何想法?

感谢线索 - 谢谢!

【问题讨论】:

    标签: ios mapkit mkpinannotationview


    【解决方案1】:

    我遇到了类似的困难,但实际上根本无法使这种方法起作用,更不用说不一致了。

    这是我发现的工作。也许它也对你有用: How to trigger MKAnnotationView's callout view without touching the pin?

    【讨论】:

    • 您好!非常感谢您的回复。当我读到这篇文章时,解决方案似乎是调用 selectAnnotation:animated: ...只是我已经在尝试了(请参阅上面的描述)并且它不起作用。也许我错过了一些额外的东西?
    • 哦!我的错。您正在谈论 发布的部分。 :) 也就是说,您浏览注释并在没有动画的情况下选择它们的部分。知道了。我会更仔细地审查,看看这是否适用于我的情况。谢谢!
    • 好的!我试了一下。我不确定它与我已经在做的事情有什么不同,结果证明它更短(不是更短总是更好......但在这里): - (void)mapView:(MKMapView *) map selectAnnotationAtIndex:(NSInteger)index animated:(BOOL)animated { [map selectAnnotation:[[map annotations] objectAtIndex:index] animated:animated]; (对我来说,animated 是 YES。)所以我已经有了一个注释列表,我什至知道索引。问题是,如果我在设置中心坐标后调用它,它可能太快了。 (见原始问题。)想法?
    【解决方案2】:

    对我有用的是从mapView:didAddAnnotationViews: 方法调用selectAnnotation:animated:

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

    同一here 上的Apple 文档。

    请注意,我在地图上只有一个注释,所以 [[mapView annotations] lastObject] 很适合我的目的。您的里程可能会有所不同。

    【讨论】:

    • 没错。一个注释很好。尝试一堆。这是不一致的。 :(
    【解决方案3】:

    我遇到了类似的问题。我正在使用带有 animatesDrop:YES 的默认 MKPinAnnotationView。在将注释添加到 MKMapView 后,我正在这样做:

    [mapView selectAnnotation:[mapView.annotations objectAtIndex:1] animated:YES]
    

    在我的程序逻辑中,应该选择最近的注释。这行不通。我找到了原因:在这个选择调用的时候,注释视图不在屏幕上,因为 pin drop 动画。所以我所做的只是设置一个计时器在一秒钟后选择注释。这是一个黑客,但它的工作原理。我不确定它是否适用于所有情况,例如在 3G 与 3G 上。最好能找到合适的回调函数放入。

    selectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self
                   selector:@selector(selectClosestAnnotation) userInfo:nil
                   repeats:NO];
    
    - (void)selectClosestAnnotation {
        [mapView selectAnnotation:[mapView.annotations objectAtIndex:1]
                 animated:YES];
    }
    

    【讨论】:

    • 太棒了!嗯,如果无法知道给定注释何时“准备就绪”(例如,如果将其添加到地图视图还不够),这可能更像是一种解决方法而不是破解!我会试一试并报告。
    【解决方案4】:

    我遇到了同样的问题,但找到了一个看似可靠且合理的解决方案:

    1. 实现委托方法mapView:didAddAnnotationViews:。当我尝试直接在委托方法中选择注释时,标注与引脚一起下降!这看起来很奇怪,所以我添加了半秒的轻微延迟。

      -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
          [self performSelector:@selector(selectInitialAnnotation)
                withObject:nil afterDelay:0.5];
      }
      
    2. 如你所愿选择初始注解,但调用 selectAnnotation:animated;

      -(void)selectInitialAnnotation {
          [self.mapView selectAnnotation:self.initialAnnotation animated:YES];
      }
      

    在某些情况下似乎没有调用selectAnnotation:animated:。与MKMapView docs比较:

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

    【讨论】:

    • 所以一切都与时机有关!非常感谢分享这个。我试试看。
    • 这似乎有效;比等待地图加载要好 - 如果您的连接速度较慢,则在显示引脚注释之前会很长时间。谢谢。
    • 这是一个很好的答案。谢谢。
    • 我必须将 '@selector(selectInitialAnnotation:)' 更改为 '@selector(selectInitialAnnotation)' 即删除冒号。我在 iOS 5.1/xcode 4.2.1
    • 这很糟糕,但似乎是正确的答案。 API 中有多大的差距。
    【解决方案5】:

    比使用固定超时更一致的方法是监听regionDidChange 回调。将地图的中心坐标设置为所需的注解,调用regionDidChange方法时,选择中心的注解,打开标注。

    这里有一个小video 我拍摄了在 5 个引脚之间随机运行的东西。

    首先,转到注解的中心坐标。假设注释对象名为thePin

    - (void)someMethod {
        [map setCenterCoordinate:thePin.coordinate animated:YES];
    }
    

    然后在regionDidChange方法中,选中这个注解。

    - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
        [map selectAnnotation:thePin animated:YES];
    }
    

    【讨论】:

    • 听起来自然/优雅!不敢相信我以前没有想到这一点。会试试这个 - 谢谢!
    • 这成功了! (是的,我终于有时间尝试了。)谢谢!
    • 哈!说得太早了。每次区域发生变化时——即使稍微移动一点,地图也会重新定向,让观众有点迷失方向。嗯。
    • 您是在进行 regionDidChange 回调后更改地图区域,还是只是选择一些注释?
    【解决方案6】:

    我发现我看到的所有解决方案都有几个问题(我想在从 viewDidAppear 添加注释时选择一个注释):

    1. 使用mapView:didAddAnnotationViews: 委托方法。

      这对我不起作用,因为如果指定的注释不在屏幕上,因此没有关联的注释视图,则此方法无效。

    2. 使用mapViewDidFinishLoadingMap: 委托方法。

      这对我也不起作用,因为地图现在被缓存了,所以该方法只被调用一次,第一次。

    解决方案:

    John Blackburn 非常接近,但没有使用mapView:didAddAnnotationViews: 方法。我只是在添加注释之前调用自己的selectAnnotation: 方法,但有延迟:

    [self.mapView addAnnotation:ann];
    [self performSelector:@selector(selectAnnotation:) withObject:ann afterDelay:0.5];
    

    这就是我在selectAnnotation: 方法中所做的:

    - (void)selectAnnotation:(id < MKAnnotation >)annotation
    {
       [self.mapView selectAnnotation:annotation animated:YES];
    }
    

    在两部 iPhone 3GS(iOS 5 和 6)和一部 iPhone 5 上测试。

    【讨论】:

    • 延迟决定一切,确实!
    【解决方案7】:

    仅供参考,这是文档所说的,

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

    所以如果我想调用 setCenterCoordinate:animated:setRegion:animated: 然后我想通过调用 selectAnnotation:animated: 来选择注释,注释将不会被选中并且标注不会因为完全相同而出现上面在文档中提到的原因,所以最好有类似setCenterCoordinate:animated:ComletionBlock 但它不存在的方式..!对我有用的方式如下,

     [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseInOut animations:^{
            [self.mapView setCenterCoordinate:location.coordinate animated:YES];
        } completion:^(BOOL finished) {
            [self.mapView selectAnnotation:location animated:YES];
        }];
    

    这将为您提供一个完成块,您可以使用它来选择注释。

    【讨论】:

    • 耶完成块!谢谢你分享这个。 :)
    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多