5

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

后台任务需要执行一些操作,例如打开领域数据库、查询结果和访问文档目录,然后才能将响应返回到课程字典。当手表输出获取课程数据时,逻辑似乎起作用。问题是我不认为后台任务实际上是在调用该方法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()如果结果是硬编码的,这也不起作用。应用程序可以在后台执行此逻辑还是应该工作?

还值得指出的是,网上没有任何地方对此进行记录,它们总是指将简单的文本响应发送回手表,而不是处理器密集型的:(

谢谢

4

3 回答 3

4

您正在用于清理的尾随闭包中进行操作。还有更多的事情是你一开始就结束后台任务,所以你的关闭永远不会调用。

这是后台任务如何工作的工作示例

 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()
于 2018-07-12T11:07:52.547 回答
3

如果您查看文档,您会看到完整的功能原型是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
}

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

于 2018-07-12T10:59:34.807 回答
1

您可以使用 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
        }
    }
于 2018-07-12T12:08:57.623 回答