2017-04-04 1 views
-1

Je suis en train de faire le travail de dispatchgroup dans mon codeDispatchGroup ne fonctionne pas à Swift 3

let dispatchQueue:DispatchQueue = DispatchQueue(label: "com.dispatchgroup", attributes: .concurrent, target: .main) 
var dispatchGroup:DispatchGroup = DispatchGroup() 
func renewLoginIfRequired()->String{ 
    self.dispatchGroup.enter() 
    dispatchQueue.async(group:dispatchGroup){ 
     self.authorizeApplication(completionHandler: { 
      self.dispatchGroup.leave() 
     }) 
    } 
    } 
    self.dispatchGroup.wait() // Stops execution here 
    return "Login Success" 
} 

code ci-dessus arrête l'exécution à self.dispatchGroup.wait(). J'ai essayé le même code sans dispatchQueue.async (groupe: dispatchGroup) autour de self.authorizeApplication ainsi sans chance Je ne suis pas sûr de ce que je fais mal. Une chose à mentionner ici est que self.authorizeApplication fera une demande de service Web async dans cette fonction

Edit 1:

Pour élaborer le problème encore plus. Je retournerai un jeton de session (String) à partir de cette méthode. est la fonction ici qui appelle cette

func processPOSTRequest(_ urlString : String, isAnAuthReq:Bool = false, requestObject: Data?, onSuccess: @escaping (NSDictionary?, NSError?) -> Void, onFailure: @escaping (Data?, NSError?) -> Void){ 
    let manager = AFHTTPSessionManager() 
    let url = URL(string: urlString); 
    var request = URLRequest(url: url!); 
    if !isAnAuthReq{ 
     let token = self.renewLoginIfRequired() //-- Get new token before processing a webservice request 
     request.setValue(token, forHTTPHeaderField: "Authorization") 
    } 
    print("processing URl : "+urlString) 
    request.httpMethod="POST"; 
    request.httpBody = requestObject 
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField:"Content-Type") 
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField:"Accept") 
    let task = manager.dataTask(with: request, uploadProgress: nil, downloadProgress: nil, completionHandler:{ data, response, error in 
     if(error == nil){ 
      if let responseCode = (data as? HTTPURLResponse)?.statusCode{ 
       if responseCode != 200 || !((response as? [String: Any])?["success"] as? Bool)!{ 
        let errorResponse = NSError() 
        print("Response received for URL: "+urlString) 
        onFailure(nil, errorResponse.addItemsToUserInfo(newUserInfo: ["errorCode":String(responseCode)])) 
       } 
       else{ 
        onSuccess(response as! NSDictionary?, nil) 
       } 
      } 

     } 
     else{ 
      onFailure(nil, error as NSError?) 

     } 
    }) 
    task.resume() 
} 

Si j'utilise Notifier ou la fermeture. Comment puis je faire ça? J'ai essayé les deux

+0

Ne faites pas cela. Utilisez un gestionnaire d'achèvement. – vadian

+0

Il me semble que vous essayez d'implémenter le sémaphore ici. Pourquoi ne pas utiliser 'DispatchSemaphore' pour votre usage? –

+1

Avez-vous essayé d'utiliser 'dispatchGroup.notify()' au lieu de 'dispatchGroup.wait()'? –

Répondre

1

Je ne sais pas ce qui est sous le capot de la demande authorizeApplication, mais il est probable que son rappel fonctionne dans le thread principal, c'est-à-dire dans la file d'attente principale. Donc, vous entrez, laissez et attendez dans la même file d'attente, donc vous ne pouvez pas atteindre le self.dispatchGroup.leave() après avoir appelé self.dispatchGroup.wait().

Pour gérer cela, vous devez repenser la demande asynchrone et appeler le self.dispatchGroup.leave() dans une file d'attente d'arrière-plan.