swift 点击一个MKAnnotation来“选择”它真的很慢

5cnsuln7  于 2023-02-03  发布在  Swift
关注(0)|答案(5)|浏览(118)

在点击和MKMapView上显示注解的标注之间几乎有0.5秒的延迟。
有人知道为什么会这样吗?我如何让它在用户点击Map时立即做出响应?
即使用户位置注解在点击时在标注中显示“当前位置”,也会发生这种情况。我希望它在点击时立即显示,没有奇怪的延迟。
编辑:我认为这是由于didSelectAnnotationView调用的setSelected函数。setSelected有一个“animated”属性,可能会减慢它的速度。我如何消除这个动画?

v440hwme

v440hwme1#

在做了大量的研究之后,我找到了一个解决这个问题的方法!它有点古怪,但它的工作就像一个魅力。
秘密是,当关闭Map的缩放时,didSelect监听器会立即触发。当我们需要缩放时(当然),我们需要做的是,暂时禁用缩放,就在didSelect事件发生的那一刻!
在Swift中:

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
gestureRecognizer.numberOfTapsRequired = 1
gestureRecognizer.numberOfTouchesRequired = 1
gestureRecognizer.delegate = self
mapView.addGestureRecognizer(gestureRecognizer)

以及

@objc func handleTap(_ sender: UITapGestureRecognizer? = nil) {
    // disabling zoom, so the didSelect triggers immediately
    mapView.isZoomEnabled = false
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        self.mapView.isZoomEnabled = true
    }
}

这个手势事件在didSelect事件之前触发,所以当didSelect事件被调用时,缩放被关闭,并且它没有延迟地触发!

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    mapView.isZoomEnabled = true // Not really necessary
    // Triggered immediately, do something
}

注意:这会禁用Map的双击手势,但我猜它们不会用得太多。所以如果你想要快速响应,你需要接受它!

vsaztqbk

vsaztqbk2#

遗憾的是,您对此无能为力。这与在移动的Safari中点击链接速度慢的原因完全相同:手势识别器不得不在它们同意你正在敲击之前拥挤一会儿以确定你是否可能正在滚动(拖动)。
所以,这与动画无关。这只是在这种情况下手势识别的本质。

ycl3bljg

ycl3bljg3#

我的解决方案是在MKAnnotationView子类上启用Map缩放并添加单独的tap处理程序。
本机缩放MKOneHandedZoomGestureRecognizer、MKZoomingPanGestureRecognizer和MKConditionalPanZoomGestureRecognizer将正常工作。
而且点击时的即时React将由注解视图上的按钮或点击识别器处理。

wribegjk

wribegjk4#

@tobidude的回答奏效了,不过还可以稍微改进一下。
不要把TapGestureRecognizer添加到Map视图中,而是在初始化时把它添加到AnnotationView子类中。这样,你就不必忽略Map视图上的所有双击。
在Swift 5中:

override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    clusteringIdentifier = MKMapViewDefaultClusterAnnotationViewReuseIdentifier
    setupGestureRecognizerToPreventInteractionDelay()
}

然后:

private func setupGestureRecognizerToPreventInteractionDelay() {
    let quickSelectGestureRecognizer = UITapGestureRecognizer()
    quickSelectGestureRecognizer.delaysTouchesBegan = false
    quickSelectGestureRecognizer.delaysTouchesEnded = false
    quickSelectGestureRecognizer.numberOfTapsRequired = 1
    quickSelectGestureRecognizer.numberOfTouchesRequired = 1
    quickSelectGestureRecognizer.delegate = self
    self.addGestureRecognizer(quickSelectGestureRecognizer)
}

最后:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    mapView?.isZoomEnabled = false
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        self.mapView?.isZoomEnabled = true
    }
    return false
}
5uzkadbs

5uzkadbs5#

这里是相同的想法与缩放禁用/启用,在一个更完整的解决方案与正确的代理模式。
1.定义代理协议并修改自定义AnnotationView的init以设置点击手势。

// MyAnnotationView.swift:
protocol MyAnnotationViewDelegate: class {    
    func didSelect(myAnnotationView: MyAnnotationView)
}

class MyAnnotationView: MKAnnotationView {
    
    weak var delegate: MyAnnotationViewDelegate?

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
            setupGestureRecognizer()
    }
    
    private func setupGestureRecognizer() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapGestureTapped))
        tapGesture.delaysTouchesBegan = false
        tapGesture.delaysTouchesEnded = false
        addGestureRecognizer(tapGesture)
    }
    
    @objc func tapGestureTapped(_ sender: AnyObject) {
        delegate?.didSelect(myAnnotationView: self)
    }
}

1.设置委托

// MapViewController.swift
extension MapViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {        
        guard let annotation = annotation as? MyAnnotation else { return nil }        
        let view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as? MyAnnotationView        
        view?.delegate = self // <--       
        return view
    }
}

1.符合我的注解视图委托

// MapViewController.swift
extension MapViewController: MyAnnotationViewDelegate  {    
    func didSelect(MyAnnotationView: MyAnnotationView) {    
        mapView.isZoomEnabled = false
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            self.mapView?.isZoomEnabled = true
        }        
    }
}

相关问题