【问题标题】:How to kill a completion handler after a specific timestamp如何在特定时间戳后终止完成处理程序
【发布时间】:2018-01-24 13:03:27
【问题描述】:

我已经在按钮操作中编写了完成处理程序,就像下面的代码一样。

func backgroundTask(arg: Bool, completion: (Bool) -> ()) {

    completion(arg)
}

在我的按钮中点击

backgroundTask(arg: true, completion: { (success) -> Void in
    if success { 
          print("true")
    } else {
         print("false")
    }
})

当用户多次按下按钮时,完成处理程序会返回那么多时间。

需要多次返回完成处理程序。

我需要打一个时间戳,之后完成处理程序不需要返回。

【问题讨论】:

  • 我们需要知道您是如何执行后台任务的。
  • 如果我正确理解了您的问题,您可以通过将其设为可选 ... completion: ((Bool) -> ())? ) 并在适当时将其设置为 nil 来终止完成处理程序。但我不确定您的具体情况以及它如何适合您的应用程序。

标签: swift background-process completionhandler


【解决方案1】:

您不能简单地取消关闭。您可以做的是创建一个包含函数调用的DispatchWorkItem,然后您可以取消工作项。与其简单地调用backgroundTask,不如在用户每次按下按钮时创建DispatchWorkItem,在项目上调用perform,如果截止日期已过,则调用取消。

自给自足的游乐场示例:

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

func backgroundTask(arg: Bool, completion: (Bool) -> ()) {
    completion(arg)
}

backgroundTask(arg: true, completion: { (success) -> Void in
    if success {
        print("true")
    } else {
        print("false")
    }
})

let workItem = DispatchWorkItem(block: { backgroundTask(arg: true, completion: {
    (success) -> Void in
    if success {
        print("true")
        DispatchQueue.main.asyncAfter(deadline: .now()+2, execute: {
            print("Delayed success") //As long as the deadline is smaller than the deadline of `workItem.cancel()`, this will be printed
        })
    } else {
        print("false")
    }
})})

workItem.perform()
DispatchQueue.main.asyncAfter(deadline: .now()+3, execute: {
    workItem.cancel()
    PlaygroundPage.current.finishExecution()
})

【讨论】:

    【解决方案2】:

    如果我理解正确,看看这是否有效:

    import UIKit
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    let completionCancelDeadline: TimeInterval = 2.5
    
    class Worker {
        init() {}
    
        private var completion: ((Bool) -> ())?
    
        func backgroundTask(arg: Bool, completion: ((Bool) -> ())?) {
            self.completion = completion
    
            DispatchQueue.main.asyncAfter(deadline: .now() + completionCancelDeadline) {
                self.completion = nil
            }
    
            worker(arg: arg)
        }
    
        private func worker(arg: Bool) {
            let randomTaskDuration = TimeInterval(arc4random_uniform(5))
    
            // randomTaskDuration is to simulate how long it's going to take the background task to complete
            // and if it completes later than the completionCancelDeadline then the completion will be nil
            DispatchQueue.main.asyncAfter(deadline: .now() + randomTaskDuration) {
                print("Time the background task took: \(randomTaskDuration) second(s)")
                print("Should the completion exist: \(randomTaskDuration < completionCancelDeadline)")
                self.completion?(arg)
                print("") // Adding a new line intentionally to separate each call
            }
        }
    }
    
    class ViewController: UIViewController {
        func buttonTap() {
            let worker = Worker()
            worker.backgroundTask(arg: true) { success in
                print("Completion called")
            }
        }
    }
    
    let vc = ViewController()
    vc.buttonTap()
    vc.buttonTap()
    vc.buttonTap()
    vc.buttonTap()
    

    【讨论】:

      猜你喜欢
      • 2014-12-19
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-26
      • 2021-05-16
      • 1970-01-01
      • 2021-09-05
      相关资源
      最近更新 更多