我想制作一个每10分钟上传多部分数据的上传管理器单例。上传本身很清楚但是如何创建一个在后面这个时间间隔上传数据的类?
只需指定:
我要上传的数据是一个包含对象数组的模型。每个对象都有一个标志,当设置了这个标志时,对象就可以上传了。整个“同步功能”应该被调用一次并且每10分钟重复一次,无论我在哪个ViewController上。有谁知道我怎么能这样做?
答案 0 :(得分:6)
代码使用了一些外部框架。它基于递归。
*上述框架并不重要。我只是用它来加快开发过程。
同步管理器
<button>
AppDelegate类
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()
})
}
请注意
要在应用进入后台时继续请求,您可能需要从应用的功能部分启用BackGroundFetchMode
答案 1 :(得分:0)
由于您希望在所有ViewControllers(VC)中调用上传方法,因此一种方法是: -
extension UIViewController
{
func uploadData(parameters) ->Bool
{
return true/false;
}
}
然后在所有ViewControllers(VC)中,您可以在viewDidLoad或特定函数中调用uploadData方法,如: -
if(self.uploadData(parameters)) // if true method is called i.e. new objects available to upload or 10mins have passed as per your requirement
{
}
第二种方法是定义NSTimer部分,该部分检查是否已经在AppDelegate中传递了10分钟并创建了一个空的Swift文件,该文件执行上传并调用AppDelegate中的didFinishLaunchingWithOptions中的方法。
有很多方法可以解决这个问题,但这取决于您的应用程序中流量的发生方式。
注意: - 使用 NSURLSessionUploadTask - &gt;上传和 NSTimer - &gt;检查是否已经过了10分钟