SWIFT Sync Manager

I want to create a Singleton that loads multi-page data every 10 minutes. The loading itself is clear, but how can I create a class that loads data into this time interval in the background?

Just to indicate:

The data I want to load is a model that has an array of objects. Each of the objects has a flag, and when this flag is set, the object is ready for loading. All this "Sync" function should be called once and repeated every 10 minutes, regardless of which ViewController I am on. Does anyone know how I can do this?

+4
source share
2 answers

The code uses some external frameworks. It is based on recursion.

* . .

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, _, _):

           // YOUR LOGIN ON SUCCESS

           // MOVE TO NEXT LOCATION
            self.moveToNextTask()

        case .Failure(_):
            // YOUR LOGIN 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

// 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
}

, , BackGroundFetchMode

+5

, ViewControllers (VC), : -

extension UIViewController
{
   func uploadData(parameters) ->Bool
   {
   return true/false;
   }
}

ViewControllers (VC) uploadData viewDidLoad , : -

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, , 10 AppDelegate, Swift, didFinishLaunchingWithOptions AppDelegate.

, , .

: - NSURLSessionUploadTask β†’ NSTimer β†’ , 10

0

Source: https://habr.com/ru/post/1649005/


All Articles