如何在特定时间戳后终止完成处理程序

Posted

技术标签:

【中文标题】如何在特定时间戳后终止完成处理程序【英文标题】: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 来终止完成处理程序。但我不确定您的具体情况以及它如何适合您的应用程序。 【参考方案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()

【讨论】:

以上是关于如何在特定时间戳后终止完成处理程序的主要内容,如果未能解决你的问题,请参考以下文章

SQL 从其他表中给定时间戳后的记录中选择

如何在特定时间后终止 JFrame?

在特定时间安排顶部/终止 Java 程序

SCUT106 花式AC 主席树版本

在 Android 中录制音频时捕获时间戳

在 iOS 应用程序终止时处理 Alamofire 请求