【问题标题】:How to run operations in background while an iOS application is in foregroundiOS 应用程序在前台时如何在后台运行操作
【发布时间】:2016-08-01 14:10:26
【问题描述】:

我在文档目录中有一个 JSON 文件,其中填充了字符串数据。在应用程序的用户界面中有一个 UIButton。按下按钮时,一个新字符串会附加到 JSON 文件中。

现在我正在寻找可以帮助我使用 swift 将这些字符串(来自 JSON 文件)发送到服务器的任何 iOS 服务。而且这个服务应该完全独立于我的代码。 关键是当我按下 UIButton 时,第一步是将字符串保存到 JSON 文件中,然后如果 Internet 可用,服务应该获取此字符串并将其发送到服务器。

当一个字符串发送成功时,它应该从 JSON 文件中删除。 此服务应每 30 秒跟踪一次是否有任何字符串保存到 JSON 文件中,然后将其发送到服务器。

我用谷歌搜索并找到了background fetch,但它会自动触发performFetchWithCompletionHandler 功能,我不知道 iOS 何时触发它。我想每隔 30 秒触发一次这种服务。

【问题讨论】:

  • 您是否为您的请求找到了解决方案?谢谢!
  • 它如何/为什么独立于您的应用程序?
  • 如果您正在寻找守护程序/服务,那么您很不幸,iOS 不支持无限期运行的自定义应用程序。
  • 谢谢大家,我通过使用带有时间间隔函数的 NSTimer 解决了我的问题,它每 30 秒调用一次我自己创建的 syncService 类方法
  • @xikitidisant 我的回答对你有帮助吗?看起来它帮助了 OP。

标签: ios swift synchronization background-fetch


【解决方案1】:

查看 Apple 的 iOS 应用程序编程指南中的 Background Execution 部分。

UIApplication 提供了一个使用UIBackgroundTaskIdentifier 启动和结束后台任务的接口。

AppDelegate 的顶层,创建一个类级任务标识符:

var backgroundTask = UIBackgroundTaskInvalid

现在,使用您希望完成的操作创建您的任务,并实现您的任务在过期之前未完成的错误情况:

backgroundTask = application.beginBackgroundTaskWithName("MyBackgroundTask") {
    // This expirationHandler is called when your task expired
    // Cleanup the task here, remove objects from memory, etc

    application.endBackgroundTask(self.backgroundTask)
    self.backgroundTask = UIBackgroundTaskInvalid
}

// Implement the operation of your task as background task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // Begin your upload and clean up JSON
    // NSURLSession, AlamoFire, etc

    // On completion, end your task
    application.endBackgroundTask(self.backgroundTask)
    self.backgroundTask = UIBackgroundTaskInvalid
}

【讨论】:

  • 请注意,如果应用程序在工作完成之前没有后台运行,这将在前台执行。
  • 好点@Cristik。我认为这是 OP 由于 Apple 限制而要求的解决方案。
  • 谢谢朋友,我已经用你提供的方法解决了我的问题。
【解决方案2】:

我所做的只是使用上面 JAL 讨论的方法。

这是我使用的三种方法

    func reinstateBackgroundTask() {
        if updateTimer != nil && (backgroundTask == UIBackgroundTaskInvalid) {
            registerBackgroundTask()
           }
    }
    func registerBackgroundTask() {
        backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
            [unowned self] in
            self.endBackgroundTask()
        }
        assert(backgroundTask != UIBackgroundTaskInvalid)
    }

    func endBackgroundTask() {
        NSLog("Background task ended.")
        UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
        backgroundTask = UIBackgroundTaskInvalid
    }

其中updateTimer 的类型为NSTIMER 类 以上函数在我自己创建的名为“syncService”的类中 这个类有一个初始化器,它是

init(){
  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.reinstateBackgroundTask), name: UIApplicationDidBecomeActiveNotification, object: nil)

        updateTimer = NSTimer.scheduledTimerWithTimeInterval(30.0, target: self, selector: #selector(self.syncAudit), userInfo: nil, repeats: true)
        registerBackgroundTask()

 }

然后我只是调用了这个类,整个问题就解决了。

【讨论】:

    【解决方案3】:
     DispatchQueue.global(qos: .background).async { // sends registration to background queue
    
     }
    

    【讨论】:

      【解决方案4】:

      请参考 NSURLSessionUploadTask 可能对你有帮助。

      【讨论】:

        【解决方案5】:

        这是 JAL 的 swift 4 版答案

          extension UIApplication {
          /// Run a block in background after app resigns activity
           public func runInBackground(_ closure: @escaping () -> Void, expirationHandler: (() -> Void)? = nil) {
               DispatchQueue.main.async {
                let taskID: UIBackgroundTaskIdentifier
                if let expirationHandler = expirationHandler {
                    taskID = self.beginBackgroundTask(expirationHandler: expirationHandler)
                } else {
                    taskID = self.beginBackgroundTask(expirationHandler: { })
                }
                closure()
                self.endBackgroundTask(taskID)
            }
          }
        
          }
        

        使用示例

        UIApplication.shared.runInBackground({
                //do task here
            }) {
               // task after expiration.
            }
        

        【讨论】:

          猜你喜欢
          • 2012-01-07
          • 1970-01-01
          • 1970-01-01
          • 2013-02-26
          • 1970-01-01
          • 2012-05-27
          • 2015-04-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多