后台任务不调用Swift中的类

时间:2018-07-12 09:57:44

标签: ios swift watchkit uibackgroundtask

我有一个后台任务,该任务应返回一系列课程,然后将其发送到Apple Watch。我正在通过didReceiveMessageWatchConnectivity内部调用任务。

后台任务需要执行一些操作,例如打开领域数据库,查询结果和访问document目录,然后将响应返回到课程字典。当手表输出其获取课程数据时,逻辑似乎起作用。问题是我不认为后台任务实际上在调用方法getWatchCourses()

DispatchQueue.global().async {

    var foundCourses = [[String : Any]]()
    let application = UIApplication.shared
    backgroundTask = application.beginBackgroundTask(withName: "app.test.getCourses") {
        let watchModel = WatchCourseModel()
        let courses = watchModel.getWatchCourses()
        print("Courses: \(courses)")
        foundCourses.append(contentsOf: courses)
    }
    replyHandler(["response": foundCourses])
    application.endBackgroundTask(backgroundTask)
    backgroundTask = UIBackgroundTaskInvalid
}

如果getWatchCourses()结果是硬编码的,那么这也不起作用。该应用程序可以在后台执行此逻辑,还是可以正常工作?

  

还值得指出的是,在线上没有任何文献记载,   他们总是指将简单的文字回复发送回手表,   不是处理器密集型的:(

谢谢

3 个答案:

答案 0 :(得分:2)

您正在使用尾随闭合进行操作,该操作用于清理。还有更多事情要在后台任务启动后立即结束,因此您的关闭将永远不会调用。

以下是工作示例,背景任务如何工作

 var backgroundTaskIdentifier:UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
 var updateTimer: Timer?

现在,当您开始运行示例运行计时器时

  updateTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self,
                                     selector: #selector(calculateNextNumber), userInfo: nil, repeats: true)
  // register background task
  beginBackgroundTask()

,当您结束计时器时,结束后台任务;应该始终不间断地结束后台任务

func beginBackgroundTask () {
    backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
      self?.endBackgroundTask() // It will call to cleanup 
    })
    assert(backgroundTaskIdentifier != UIBackgroundTaskInvalid)
  }

  func endBackgroundTask () {
    UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
    backgroundTaskIdentifier = UIBackgroundTaskInvalid
  }

所以就您而言

  • 注册后台任务
  • 查询数据库(执行所有操作)
  • 完成通话结束后台任务

注意:还请注意苹果给出的执行后台任务的时间限制

编辑

确保已从项目设置中启用了后台功能

尝试

    beginBackgroundTask()

    let watchModel = WatchCourseModel()
    let courses = watchModel.getWatchCourses()
    print("Courses: \(courses)")
    foundCourses.append(contentsOf: courses)
    endBackgroundTask()

答案 1 :(得分:1)

如果您选中documentation,将会看到完整功能的原型为beginBackgroundTask(withName:expirationHandler:)

您通过尾随闭包指定的代码为expirationHandler-如果在允许的后台执行时间用尽之前不调用endBackgroundTask,则会调用该代码。到期处理程序为您提供了最后的机会,可以在终止应用程序超过其后台时间之前执行任何清理操作。

由于几乎立即调用endBackgroundTask并从函数返回,因此不会调用到期处理程序。

您真正想要的是类似的东西

var foundCourses = [[String : Any]]()
let application = UIApplication.shared
backgroundTask = application.beginBackgroundTask(withName: "app.test.getCourses") {
DispatchQueue.global().async {
    let watchModel = WatchCourseModel()
    let courses = watchModel.getWatchCourses()
    print("Courses: \(courses)")
    foundCourses.append(contentsOf: courses)
    replyHandler(["response": foundCourses])
    application.endBackgroundTask(backgroundTask)
    backgroundTask = UIBackgroundTaskInvalid
}

这将启动后台任务,然后您异步执行工作并将结果传递回手表并结束后台任务。

答案 2 :(得分:0)

您可以通过将QOS类型用作.background来创建后台任务

DispatchQueue.global(qos: .background).async {
        //background code
        var foundCourses = [[String : Any]]()
        let application = UIApplication.shared
        backgroundTask = application.beginBackgroundTask(withName: "app.test.getCourses") {
            let watchModel = WatchCourseModel()
            let courses = watchModel.getWatchCourses()
            print("Courses: \(courses)")
            foundCourses.append(contentsOf: courses)
        }
        replyHandler(["response": foundCourses])
        DispatchQueue.main.async {
            //your main thread
        }
    }