2016-04-28 1 views
0

J'ai un service Web qui renvoie une réponse dans json. J'ai créé une classe séparée pour l'accès aux données dans xcode (swift) pour iphone. Ce que je veux faire est d'appeler une fonction dans la couche d'accès aux données, qui renvoie le dictionnaire de réponse, WHEN FETCHING IS COMPLETE. Problème: Comment retourner SEULEMENT quand la récupération du service est terminée. Ex: Étudiant Tableau-> Cliquez sur un étudiants> Fetch données étudiants> Retour des données lors de la récupération termine IOS SWIFT - Renvoie les données de réponse lorsque l'appel de service a terminé l'extraction

func getUser(userID:String)->NSDictionary{ 

     let manager = AFHTTPRequestOperationManager() 
     let parameters = ["uid":userID] 
     manager.POST(urlStudentInfo, parameters: parameters, 
      success: {(operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in 
       print("JSON success: " + responseObject.description) 
       if let responseDic = responseObject as? NSDictionary{ 
        let isUser = responseDic["status"] as! Bool 

        if isUser{ 



        }else{ 

        } 
       } 

      }, 

      failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in 

     }) 

    return response 

} 

Ceci est ma structure de fonction. Le problème est la récupération se produit après le retour est terminé. Donc le retour est toujours nul.

Quelqu'un at-il une suggestion à retourner seulement après la fin de la récupération?

+0

Veuillez spécifier {callService} –

+0

mis à jour la partie {callService} –

Répondre

1

En quoi votre {callService} ressemble-t-elle réellement? A-t-il un gestionnaire d'achèvement? mais en général, les fonctions asynchrones comme webservices ne peuvent pas être considérées de la même manière qu'une fonction normale, vous devez lancer l'appel ws dans une fonction, puis appeler une autre fonction pour laisser quelque chose savoir à partir du gestionnaire d'achèvement, ou tout la fonction ws sait qu'elle est terminée. Donc en bref, vous ne devriez pas essayer de retourner quoi que ce soit de cette fonction, et de revenir à la place la valeur du gestionnaire d'achèvement

modifier:

Je vous conseille de ne pas utiliser NSNotifications, mais déléguer plutôt callbacks, ou tout simplement utilisez les données dans le gestionnaire d'achèvement directement. mais tout ce qui essaie d'utiliser ce NSDictionary retourné devrait plutôt être un délégué de la classe dans laquelle cette fonction est (cherchez des tutoriels sur les protocoles si vous ne savez pas comment cela fonctionne), alors vous pouvez passer le dictionnaire par les callbacks délégués dans l'achèvement gestionnaire (pensez à comment UITableviews vous faire mettre en œuvre toutes ces fonctions pour le faire fonctionner, vous devez faire quelque chose de similaire pour votre appel webservice)

this answer peut vous aider à comprendre ce que je veux dire

+0

Oui, j'ai des gestionnaires de complétion dans le service. J'ai essayé avec NSNotification. Je peux donc envoyer la réponse dans l'objet. Mais cela nécessite de gérer 3 états (services de succès accessibles, paramètres de défaillance-erreur, service de panne non accessible) dans 1 appel de service et il y a beaucoup de service auquel j'accède. Il n'est donc pas possible de l'utiliser toujours puisque je dois avoir des listes pour de nombreux appels. –

+0

Méthodes de délégué testées, c'est une bonne solution. Travaux. –

+0

heureux d'entendre, peut marquer la réponse comme résolu alors, malade peut-être mettre à jour la réponse avec le contenu de mon commentaire – Fonix

0

Parce que vous appelez asynchrone méthode, vous ne devriez pas essayer de retourner immédiatement une valeur. Au lieu de cela, fournissez une fermeture de «gestionnaire d'achèvement» que vous pouvez appeler lorsque les résultats sont renvoyés ultérieurement.

Je voudrais aussi vous suggérons d'utiliser 3.x AFNetworking, à tout le moins (parce que le AFHTTPRequestOperationManager de AFNetworking 2.x utilise NSURLConnection, qui est maintenant dépréciée):

func getUser(userID:String, completionHandler: (NSDictionary?, NSError?) ->()) { 
    let manager = AFHTTPSessionManager() 
    let parameters = ["uid":userID] 
    manager.POST(urlStudentInfo, parameters: parameters, progress: nil, success: { task, responseObject in 
     if let responseDic = responseObject as? NSDictionary, let isUser = responseDic["status"] as? Bool { 
      if isUser{ 
       completionHandler(responseDic, nil) 
      } else { 
       let error = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 1, userInfo: [NSLocalizedDescriptionKey: "status false"]) 
       completionHandler(nil, error) 
      } 
     } else { 
      let error = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 2, userInfo: [NSLocalizedDescriptionKey: "Response not dictionary; or status not found"]) 
      completionHandler(nil, error) 
     } 
    }, failure: { task, error in 
     completionHandler(nil, error) 
    }) 
} 

Et vous appelez comme si:

getUser(userID) { responseDictionary, error in 
    guard responseDictionary != nil && error == nil else { 
     print(error) 
     return 
    } 

    // do something with responseDictionary here 
} 

// but do not try to use responseDictionary here, because the above runs asynchronously 

Ou, mieux encore, vous pourriez envisager d'utiliser Alamofire. Voir https://stackoverflow.com/a/27393174/1271826 par exemple.