web-dev-qa-db-fra.com

Retour rapide des données depuis URLSession

Je ne peux pas renvoyer de données de ma requête HTTP et je ne parviens pas non plus à faire fonctionner les gestionnaires d'achèvement. Alors aidez-moi dans ma quête pour résoudre ce problème:

public static func createRequest(qMes: message, location: String, method: String) -> String{
    let requestURL = URL(string: location)
    var request = URLRequest(url: requestURL!)

    request.httpMethod = method
    request.httpBody = qMes.toString().data(using: .utf8)

    let requestTask = URLSession.shared.dataTask(with: request) {
        (data: Data?, response: URLResponse?, error: Error?) in

        if(error != nil) {
            print("Error: \(error)")
        }

        return String(data: data!, encoding: String.Encoding.utf8) as String!
    }
    requestTask.resume()
}

Il s’agit d’une instruction de retour non vide dans la fonction vide. À ce stade, je suis désemparé ...

6
Craz1k0ek

Vous pouvez utiliser cette méthode de bloc d'achèvement pour envoyer la réponse finale:

Par exemple: .__ J'ai renvoyé String dans le bloc d'achèvement, après une réponse réussie sans erreur, il suffit de transmettre le résultat dans le bloc.

  public func createRequest(qMes: String, location: String, method: String , completionBlock: @escaping (String) -> Void) -> Void
    {

        let requestURL = URL(string: location)
        var request = URLRequest(url: requestURL!)

        request.httpMethod = method
        request.httpBody = qMes.data(using: .utf8)

        let requestTask = URLSession.shared.dataTask(with: request) {
            (data: Data?, response: URLResponse?, error: Error?) in

            if(error != nil) {
                print("Error: \(error)")
            }else
            {

                let outputStr  = String(data: data!, encoding: String.Encoding.utf8) as String!
                //send this block to required place
                completionBlock(outputStr!);
            }
        }
        requestTask.resume()
    } 

Vous pouvez utiliser ce code ci-dessous pour exécuter la fonction de bloc d'achèvement ci-dessus:

 self.createRequest(qMes: "", location: "", method: "") { (output) in

        }

Cela résoudra votre exigence suivante.

{
    (data: Data?, response: URLResponse?, error: Error?) in

    if(error != nil) {
        print("Error: \(error)")
    }

    return String(data: data!, encoding: String.Encoding.utf8) as String!
}

Cette partie de votre code est le gestionnaire d'achèvement de la méthode dataTask(). C'est un bloc de code que vous transmettez à la méthode dataTask() pour être exécuté ultérieurement (lorsque le serveur renvoie des données ou en cas d'erreur). Ce n'est pas exécuté tout de suite.

Cela signifie que lorsque votre méthode createRequest() ci-dessus est en cours d'exécution, elle passe directement sur ce code, puis sur la ligne requestTask.resume(), puis la méthode se termine. À ce stade, comme votre méthode est définie comme renvoyant une String, vous devez renvoyer une String. Le renvoyer du gestionnaire d'achèvement n'est pas bon car cela n'a pas encore été exécuté, cela sera exécuté plus tard.

Il y a beaucoup de façons différentes de gérer la programmation asynchrone, mais l'une des façons de le faire est de changer votre méthode createRequest() de sorte qu'elle ne soit pas définie pour renvoyer une String, créez une méthode qui prend une String comme paramètre faisant tout ce que vous voulez. faire avec la valeur de retour, puis appelez cette méthode à partir de votre gestionnaire d'achèvement.

2
Jim

Juste dans votre appel de fonction

var webString = try String(contentsOf: URL(string: url)!)

Et vous avez une réponse complète en chaîne, que vous pouvez retourner

1
Vadim

Au lieu d'utiliser return, essayez d'utiliser les gestionnaires d'achèvement comme vous l'avez mentionné dans votre question.

func createRequest(qMes: message, location: String, method: String, completionHandler: @escaping (_ data:Data?, _ response: URLResponse?, _ error: NSError?) -> Void)

Ensuite, au lieu de return, vous devriez utiliser quelque chose comme completionHandler(data, response, error)

Et voici comment vous faites la demande:

var request = URLRequest(url: Foundation.URL(string: URL)!)
        request.httpMethod = method
        //request.addValue(authString, forHTTPHeaderField: "Authorization") // if you need some

        let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in

            guard error == nil && data != nil else
            {
                print("error=\(error)")
                completionHandler(data, response, error as NSError?)
                return
            }

            completionHandler(data, response, error as NSError?)
        }) 

        task.resume()
1
Slavcho