当iOS应用程序在前台时,如何在后台运行操作

时间:2023-02-10 01:26:05

I have a JSON file populated with strings data in Documents Directory. In user Interface of application there is a UIButton. On button press, a new string appends into the JSON file.

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

Now I am looking for any iOS Service that helps me to send these strings (from JSON file) to the server using swift. And this service should be totally independent of my code. The point is when I press a UIButton, the first step is a string is saved to the JSON file then service should take this string and send it to server if Internet is available.

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

When a string sent successfully, it should be removed from the JSON file. This service should track after every 30 seconds if there is any string saved into JSON file, then send it to server.

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

I Googled and found background fetch but It triggers performFetchWithCompletionHandler function automatically and I cannot know when iOS triggers it. I want to trigger this kind of service my self after every 30 seconds.

我在google上搜索并找到了后台取回,但它会自动触发performFetchWithCompletionHandler函数,我不知道什么时候iOS会触发它。我想每隔30秒就触发一次这种服务。

5 个解决方案

#1


9  

Review the Background Execution portion of Apple's App Programming Guide for iOS.

查看苹果iOS应用程序编程指南的后台执行部分。

UIApplication provides an interface to start and end background tasks with UIBackgroundTaskIdentifier.

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

In the top level of your AppDelegate, create a class-level task identifier:

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

var backgroundTask = UIBackgroundTaskInvalid

Now, create your task with the operation you wish to complete, and implement the error case where your task did not complete before it expired:

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

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
}

#2


3  

What I have done is I just uses the approach discussed by JAL above.

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

these were the three methods which I used

这就是我使用的三种方法

    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
    }

where updateTimer is of type NSTIMER class The above functions are in my own created class named "syncService" This class has an initialiser which is

如果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()

 }

Then I just called this class and the whole problem is solved.

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

#3


1  

Please refer NSURLSessionUploadTask might it help you.

请参考NSURLSessionUploadTask,它可能对您有所帮助。

#4


1  

 DispatchQueue.global(qos: .background).async { // sends registration to background queue

 }

#5


0  

Here is the swift 4 version of the answer by 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)
    }
  }

  }

Usage Example

使用的例子

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

#1


9  

Review the Background Execution portion of Apple's App Programming Guide for iOS.

查看苹果iOS应用程序编程指南的后台执行部分。

UIApplication provides an interface to start and end background tasks with UIBackgroundTaskIdentifier.

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

In the top level of your AppDelegate, create a class-level task identifier:

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

var backgroundTask = UIBackgroundTaskInvalid

Now, create your task with the operation you wish to complete, and implement the error case where your task did not complete before it expired:

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

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
}

#2


3  

What I have done is I just uses the approach discussed by JAL above.

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

these were the three methods which I used

这就是我使用的三种方法

    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
    }

where updateTimer is of type NSTIMER class The above functions are in my own created class named "syncService" This class has an initialiser which is

如果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()

 }

Then I just called this class and the whole problem is solved.

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

#3


1  

Please refer NSURLSessionUploadTask might it help you.

请参考NSURLSessionUploadTask,它可能对您有所帮助。

#4


1  

 DispatchQueue.global(qos: .background).async { // sends registration to background queue

 }

#5


0  

Here is the swift 4 version of the answer by 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)
    }
  }

  }

Usage Example

使用的例子

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