【问题标题】:can't start beginBackgroundTask swift 3无法开始beginBackgroundTask swift 3
【发布时间】:2018-03-15 23:48:14
【问题描述】:

对不起,我卡住了,但我正在尝试启动后台任务(XCode8,swift 3)

此处的示例: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW3

在 AppDelegate.swift 中:

func applicationDidEnterBackground(_ application: UIApplication) {
    var bgTask: UIBackgroundTaskIdentifier = 0;
    bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: {() -> Void in
        print("The task has started")
        application.endBackgroundTask(bgTask)
        bgTask = UIBackgroundTaskInvalid
    })
}

该应用从未显示“任务已启动”消息。我做错了什么?

【问题讨论】:

  • 我认为expirationHandler的意思是在后台任务完成后立即执行。
  • @Christoph 不管怎样,消息应该会出现

标签: ios swift background-task


【解决方案1】:

你对后台任务的使用都是错误的。

等待到期处理程序被调用以调用endBackgroundTask 是一种糟糕的做法,并且会使您的应用浪费比它需要的更多的资源。当你的后台任务完成时,你应该立即告诉 iOS。

所以你应该这样做:

func applicationDidEnterBackground(_ application: UIApplication) {
    var finished = false
    var bgTask: UIBackgroundTaskIdentifier = 0;
    bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: {() -> Void in
        // Time is up.
        if bgTask != UIBackgroundTaskInvalid {
            // Do something to stop our background task or the app will be killed
            finished = true
        }
    })

    // Perform your background task here
    print("The task has started")
    while !finished {
        print("Not finished")
        // when done, set finished to true
        // If that doesn't happen in time, the expiration handler will do it for us
    }

    // Indicate that it is complete
    application.endBackgroundTask(bgTask)
    bgTask = UIBackgroundTaskInvalid
}

另外请注意,即使应用程序进入后台,您也应该在任何类中的任何代码周围使用beginBackgroundTask/endBackgroundTask,以便在短时间内保持运行。

在此设置中,如果在 while 循环仍在工作时任务未完成,则在 不同的线程上并行调用 expirationHandler。您应该使用处理程序来停止您的代码并允许它到达application.endBackgroundTask(bgTask) 行。

【讨论】:

  • @maddy - 你也是对的,但我不明白什么时候应该执行 expireHandler 中的代码块。
  • @rmaddy 你的代码不正确吗?我的意思是,如果那行打印需要 20 分钟。 (这里不会发生),然后从 expireHandler 调用 application.endBackgroundTask(bgTask),这会导致崩溃......
  • @Honey 这就是过期处理程序的用途。看到我的评论“做点什么来阻止......”?那个“做某事”就是做一些事情来停止你正在进行的任何运行时间过长的后台任务。显然print 不会花费太长时间。但是假设您有一个持续时间过长的while 循环。过期处理程序需要设置一个在while 循环中检查的变量,以便while 循环在下一次迭代时自行停止。这至少是一个例子。
  • @Honey 我确实打电话给endBackgroundTask。它在 print 之后调用(或在我之前评论中的 while 之后)。调用 endBackgroundTask 告诉 iOS 你的代码已经完成。但是您实际上还需要先停止您的代码。调用endBackgroundTask 不会停止我长时间运行的while 循环。我需要先停止循环。停止循环的结果将是代码到达我对endBackgroundTask 的调用。
  • @Honey endBackgroundTask 应该在您的代码实际完成时调用。所以在我的例子中,在过期处理程序中调用endBackgroundTask 是没有意义的。您是正确的,过期处理程序是异步的。将调用处理程序,设置标志,停止循环,并调用 endBackgroundTask
【解决方案2】:

过期处理程序块在后台运行一段时间(通常为 5 分钟左右)后被调用。 如果您的后台任务需要很长时间才能完成,这将用于编写清理逻辑。

您的代码没有问题,您只需要在后台等待后台任务到期即可。

【讨论】:

  • 代码有问题。编写代码就像立即调用过期处理程序一样。打印语句不应在过期处理程序中。也不应该打电话给application.endBackgroundTask(bgTask)。两者都应该在调用beginBackgroundTask之后。
  • @rmaddy:print中的说法是错误的,但是可以在这个handler中调用application的endBackgroundTask来防止系统杀掉app。
  • @Puneet Sharma 你是对的。 3-4 分钟后,消息出现
  • @PuneetSharma 等待到期处理程序被调用以调用 endBackgroundTask 是一种糟糕的做法,并且会使您的应用程序浪费比它需要的更多的资源。当你的后台任务完成时,你应该立即告诉 iOS。
  • @Alex 正好是 3 分钟
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多