web-dev-qa-db-fra.com

Comment utiliser la tâche en arrière-plan en utilisant Swift 3?

Je suis nouveau dans les tâches d'arrière-plan. J'ai un petit travail que je récupère des tweets et si mon application est en mode arrière-plan, elle devrait également récupérer les tweets, mais je ne sais pas comment.

J'utilise simplement Timer dans la méthode Appdelegate didFinishLaunchOption. Lorsque je ferme l'application, cela ne fonctionne pas. Je suis nouveau dans ce domaine, veuillez donc toute suggestion. Voici ci-dessous mon code:

Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(getTweets), userInfo: nil, repeats: true). 

func getTweets() {

    let locationName = Helper.sharedInstance.userDefault.value(forKey: ModelKey.currentLocation) as? String

    let accessToken = Helper.sharedInstance.userDefault.value(forKey: ModelKey.twitterAccessToken) as? String

    if (locationName == "Bengaluru" && nil != accessToken) || (locationName == "Bangalore" && nil != accessToken){
        tweetModel.getTweets(accessToken: accessToken!, city: ModelKey.blrcitytraffic, cityName: "Bengaluru")
    }
}

La synthèse vocale est également présente, mais lorsque je ferme l'application, elle cesse de parler. Si je n'utilise pas l'application, elle peut également récupérer les tweets et la synthèse vocale devrait fonctionner en utilisant un mode d'arrière-plan. Combien de temps ça marche?

7
kishor0011

Vous devez faire trois choses:

  1. Dans votre Info.plist, ajoutez l'entrée suivante pour la clé Required background modes pour autoriser l'accès au réseau en arrière-plan:

    Required background modes:App downloads content from the network

  2. Dans votre AppDelegate, ajoutez à votre applicationDidEnterBackground ():

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Fetch no sooner than every (60) seconds which is thrillingly short actually. 
        // Defaults to Infinite if not set. 
        UIApplication.shared.setMinimumBackgroundFetchInterval( 60 ) )
    }
    
  3. Également dans l'implémentation AppDelegate

    func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
      var fetchResult: UIBackgroundFetchResult!
    
    
      if doingYourStuffActuallyCreatesNetworkTraffic() {
        fetchResult = UIBackgroundFetchResult.newData
      } else if thereWasAnError() { 
        fetchResult = UIBackgroundFetchResult.failed
      } else {
        fetchResult = UIBackgroundFetchResult.noData
      }           
      completionHandler( fetchResult )
    
      return    
    }
    

Il y a encore quelques pièges, par exemple il n'y a pas d'intervalle de récupération maximum garanti, et l'exécution en arrière-plan peut se comporter de manière sensiblement différente dans XCode/Simulator que sur des appareils réels.

Vous pouvez jeter un oeil à ce sujet assez similaire:

performFetchWithCompletionHandler n'est jamais viré

et bien sûr https://developer.Apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

10
christian.buggle

Une tâche en arrière-plan signifie que vous devez utiliser des fils d'arrière-plan. Les threads dans iOS sont trop nombreux, mais si vous souhaitez effectuer uniquement une tâche en arrière-plan, vous devez utiliser deux threads; le fil principal et d'arrière-plan que leur structure est:

DispatchQueue.global(qos: .background).async {
    //background code
    DispatchQueue.main.async {
        //your main thread
    }    
}

Donc, vous initialisez d'abord la file d'attente globale avec le mode d'arrière-plan. Ce thread peut être utilisé pour la tâche en arrière-plan, puis vous devez utiliser le thread principal (uniquement si vous le souhaitez) pour faire quelque chose lorsque la tâche en arrière-plan est terminée. Cela peut être une option. Une autre option devrait être applicationDidEnterBackground dans appDelegate et vous ne pouvez que mettre votre code dans cette méthode.

10
Alfredo Luco G