在 MKMapViewDelegate 中执行代码之前设置一个计时器

Set a timer before executing code in MKMapViewDelegate

使用 MKMapView,我想捕捉用户完成将地图移动到另一个区域的时刻,然后在该区域显示注释。

为了捕捉他完成移动地图的那一刻,我使用:

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool){
}

不过,我会在调用委托内的代码之前添加 1 秒的延时,以防用户开始稍微移动相机。如果用户在这段时间结束之前再次移动地图,它当然会取消代码的执行。

有什么想法吗?

声明一个计时器:

var delayTimer:Timer? = nil

然后写这些方法:

private func stopDelayTimer(){
    self.delayTimer?.invalidate()
    self.delayTimer = nil
}

private func startDelayTimer(timeIntervalInSecond : Int){
    self.stopDelayTimer()

    delayTimer = Timer.scheduledTimer(timeInterval:TimeInterval(timeIntervalInSecond),target:self,selector:#selector(onDelayTimeOut), userInfo: nil, repeats: false)
}

@objc fileprivate func onDelayTimeOut(){
        //do Your  work here
}

从您的委托方法开始调用:

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool){
self.startDelayTimer(timeIntervalInSecond: 1)
}

onDelayTimeOut() 将在您提供的时间间隔

后被调用

URLSessionDataTask 类型创建一个 属性 并在地图视图委托方法中调用 cancel 方法

class ViewController: UIViewController {

    var task: URLSessionDataTask?

    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool){
        task?.cancel()
        perform(#selector(fetchDetails), with: self, afterDelay: 1.0)
    }

    @objc func fetchDetails() {

        let request = URLRequest(url: URL(string: "yourURL")!)
        task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in

        })
        task?.resume()
    }
}

实现此目的的一种方法是使用 DispatchWorkItem,一个封装了一些代码以便稍后执行的对象。当用户再次开始移动地图视图时,您可以在 mapView(_:regionWillChangeAnimated:) 方法中取消工作项:

class YourClass: NSObject, MKMapViewDelegate {
    private var userFinishedMovingMapViewWorkItem: DispatchWorkItem?

    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        // Cancel any previous work item
        userFinishedMovingMapViewWorkItem?.cancel()
    }

    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        // Create a new work item, store it in a property, and set it to execute
        // on the main queue after one second from now
        let workItem = DispatchWorkItem(qos: .userInteractive) {
            // Code you want to execute after 1 second
        }

        userFinishedMovingMapViewWorkItem = workItem
        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: workItem)
    }
}