gpt4 book ai didi

ios - Swift 后台同步管理器

转载 作者:搜寻专家 更新时间:2023-10-31 08:22:40 25 4
gpt4 key购买 nike

我想制作一个上传管理器单例,每 10 分钟上传一次分段数据。上传本身是清楚的,但是如何在后台创建一个在这个时间间隔内上传数据的类?

只是为了说明:

我要上传的数据是一个包含对象数组的模型。每个对象都有一个标志,设置此标志后,对象就可以上传了。整个“同步功能”应该调用一次并每 10 分钟重复一次,无论我在哪个 ViewController 上。有谁知道我该怎么做?

最佳答案

代码使用了一些外部框架。它基于递归。

  1. Alamofire//用于网络

*以上框架不重要。我只是用它来加快开发过程。

Sync Manager

import Foundation
import Alamofire


let SyncMangerIdentifier = "com.example.background.syncmanger"

class SyncManager: Alamofire.Manager{

static let instance = SyncManager()
private var pendingTasks = [SyncTask]() // SyncTask is a class with 3 variables [image,audio,[tags]] that are being uploading to server
private var request: Request?
private var isSyncing = false


private init(){
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(SyncMangerIdentifier)
configuration.allowsCellularAccess = Config.cellularAccess
super.init(configuration: configuration)
}

// CALL THIS FUNCTION TO START THE SYNC
// variable isSyncing guards multiple execution of syncManager
func start(){
guard !isSyncing else {
// WE ARE ALREADY SYNCING
return
}

// CALL TO PREPARE FUNCTION TO EVALUATE WHETHER WE CAN SYNC OR NOT
prepare()
}


/*
initialize the syncItem variable with the first entry from SyncTask
if we are stopping return
if syncTask isEmpty stop
if there are no items in first syncTask remove the task and restart the process.

*/
private func prepare(){

// I use a database query to store & retrieve pendingTasks

guard !pendingTasks.isEmpty else{
// todo no more data to sync
isSyncing = false // syncing process ended

// Notify app that your long running task has finished
(UIApplication.sharedApplication().delegate as? AppDelegate)?.endBackgroundSyncTask()
return
}

isSyncing = true // we are in syncing process

// Notify app that our long running task has begun
(UIApplication.sharedApplication().delegate as? AppDelegate)?.beginBackgroundRestoreTask()

// Call function to start the first upload
uploadFileOrData()
}
}


/**
upload the files & data from array recursively
*/
private func uploadFileOrData(){
var task = pendingTasks[0]

let imageUrl = task.imageUrl
let audioUrl = task.audioUrl
let tags = task.tags.reduce(""){ prev, next in
if prev.isEmpty{
return next.text
}
return "\(prev),\(next.text)"
}

let form : (MultipartFormData) -> () = { data in

if imageUrl.checkResourceIsReachableAndReturnError(nil){
data.appendBodyPart(fileURL: imageUrl, name: "image")
}

if audioUrl.checkResourceIsReachableAndReturnError(nil){
data.appendBodyPart(fileURL: audioUrl, name: "audio")
}
data.appendBodyPart(data: tags.dataUsingEncoding(NSUTF8StringEncoding,allowLossyConversion: false)!, name: "tags")

}

upload(.POST, Api.fileUploadUrl, multipartFormData: form ,encodingCompletion: {

// Call function to process the response
self.processUploadFileResponse($0)
})
}

private func processUploadFileResponse(result: Manager.MultipartFormDataEncodingResult){
switch result {
case .Success(let upload, _, _):

// PERFORM ACTION ON SUCCESS

// MOVE TO NEXT LOCATION
self.moveToNextTask()

case .Failure(_):
// PERFORM ACTION ON FALIURE

// MOVE TO NEXT LOCATION
self.moveToNextTask()
}
}




private func moveToNextTask(){
// DELETE pendingTasks[0] & CALL prepare() function

// If you want to repeat after every 10 MINUTE
// Then wrap your function call 'prepare()' inside dispatch_after


dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(10 * 60 * Double(NSEC_PER_SEC)) // 10 * 60 to convert seconds into minute
),
dispatch_get_main_queue(), {
self.prepare()
})

}

AppDelegate class

// bind the alamofire backgroundCompletionHandler
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
// NSLog("handle events for background: \(identifier)")
if identifier == SyncMangerIdentifier{
SyncManager.instance.backgroundCompletionHandler = completionHandler
}
}

// Identifier for long running background task for SyncManager class
var backgroundSyncTask: UIBackgroundTaskIdentifier?

// Call this at the beginning of syncing
func beginBackgroundSyncTask() {

backgroundRestoreTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
self.endBackgroundRestoreTask()
})
}

// Call this when syncing process ends
func endBackgroundSyncTask() {

guard backgroundSyncTask != nil else {
return
}
UIApplication.sharedApplication().endBackgroundTask(self.backgroundSyncTask!)
self.backgroundSyncTask = UIBackgroundTaskInvalid
}

Note

为了在您的应用进入后台时继续请求,您可能需要从应用的功能部分启用 BackGroundFetchMode

关于ios - Swift 后台同步管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38563154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com