【问题标题】:How do I pass params on timer selector [duplicate]如何在计时器选择器上传递参数 [重复]
【发布时间】:2017-12-30 07:33:08
【问题描述】:
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let mostRecentLocation = locations.last else {
            return
        }

        print(mostRecentLocation.coordinate.latitude)
        print(mostRecentLocation.coordinate.longitude)        
        Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(StartTestVC.sendDataToServer), userInfo: nil, repeats: true)
    }

    func sendDataToServer (latitude: Double, longitude: Double) {
        SFUserManager.shared.uploadPULocation(latitude, longitude:longitude)
    }

我想每 1 分钟向服务器发送一次数据。我正在使用 Timer.scheduledTimer 和设置选择器。但是我怎样才能将 lat/lng 参数发送到我的函数?

【问题讨论】:

  • 您可以将您的位置作为类变量并发送
  • 是的,我知道要通过选择器发送什么?
  • @pmb 你只需要去掉输入参数并直接在你的函数中使用类属性。请参阅下面的答案。

标签: ios swift swift3 core-location


【解决方案1】:

要使用Timer 发送数据,您可以使用userInfo 参数来传递数据。

这是一个示例,您可以通过该示例调用选择器方法并将您的位置坐标传递给它。

Timer.scheduledTimer(timeInterval: 0.5, target: self, selector:#selector(iGotCall(sender:)), userInfo: ["Name": "i am iOS guy"], repeats:true)

要处理userInfo,您需要按照以下说明进行操作。

func iGotCall(sender: Timer) {
    print((sender.userInfo)!)
}

根据您的情况,请确保您的 didUpdateLocations 经常被调用。

【讨论】:

  • iGotCall 每隔一秒调用一次,即使我设置了 1 秒。为什么?
  • 一分钟时间间隔应该是 60 所以它是 timeInterval: 60
  • 是的,我知道我将它设置为 60,但它延迟了 60 秒,然后每 1 秒调用一次 IGotCall
  • 您是从其他任何地方呼叫 iGotCall 吗?
  • 不,它没有被调用
【解决方案2】:

这正是userInfo 参数的用途:

struct SendDataToServerData { //TODO: give me a better name
    let lastLocation: CLLocation
    // Add other stuff if necessary
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let mostRecentLocation = locations.last else { return }

    print(mostRecentLocation.coordinate.latitude)
    print(mostRecentLocation.coordinate.longitude)

    Timer.scheduledTimer(
        timeInterval: 60.0,
        target: self,
        selector: #selector(StartTestVC.sendDataToServer(timer:)),
        userInfo: SendDataToServerData(mostRecentLocation: mostRecentLocation),
        repeats: true
    )
}

// Only to be called by the timer
func sendDataToServerTimerFunc(timer: Timer) {
    let mostRecentLocation = timer.userInfo as! SendDataToServerData
    self.sendDataToServer(
        latitude: mostRecentLocation.latitude
        longitude: mostRecentLocation.longitude
    )
}

// Call this function for all other uses
func sendDataToServer(latitude: Double, longitude: Double) {
    SFUserManager.shared.uploadPULocation(latitude, longitude:longitude)
}

【讨论】:

  • sendDataToServer 每隔一秒调用一次,即使我设置了 1 秒。为什么?
  • @pmb 嗯?你打错字了吗?
  • 我复制了您的代码,做了一些更改,但 sendDataToServer 在 1 分钟后调用,但之后它开始每隔 1 秒调用一次
  • @pmb Idk 根据您提供的少量信息,您希望我如何帮助您
  • 您的代码是否适合您?我正在使用您的代码,但它不起作用。我刚刚复制了您的代码,并修复了错误
【解决方案3】:

确保您的sendDataToServer 始终上传最新坐标而不将坐标作为输入参数输入函数的一种方法是将值存储在一个范围内,该范围可以由函数访问并在其中使用这些值函数。

假设您将mostRecentLocation 设为类属性,您可以使用以下代码

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let mostRecentLocation = locations.last else {
        return
    }   

    self.mostRecentLocation = mostRecentLocation
    Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(StartTestVC.sendDataToServer), userInfo: nil, repeats: true)
}

func sendDataToServer() {
    SFUserManager.shared.uploadPULocation(self.mostRecentLocation.coordinate.latitude, longitude:self.mostRecentLocation.coordinate.longitude)
}

【讨论】:

  • @Dnvid 但根本没有调用 sendDataToServer
  • 更改前是否有效?你没有在你的问题中提到它没有被调用。如果之前都不起作用,是否调用了 didUpdateLocations?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
  • 2022-01-18
  • 2012-08-31
  • 1970-01-01
相关资源
最近更新 更多