web-dev-qa-db-fra.com

Swift 3: URLSession/URLRequest ne fonctionne pas

J'essaie toujours de convertir notre application de Swift 2 à Swift 3 parce que je suis obligé de le faire, car tous nos appareils Apple utilisent maintenant iOS 10. 

Après avoir converti le code, je pensais que tout allait bien, alors que je tentais de déboguer mes problèmes JSON (publiés dans une autre question), je traite maintenant des demandes qui ne sont même pas envoyées.

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    var request = URLRequest(url: URL(string: "http://domain.tld/path/")!)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    NSLog("Got here?")

    session.dataTask(with: request) {data, response, error in
        guard let data = data, error == nil else {
            print("error=\(error)")
            return
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data)

        NSLog("Object: \(object)")
    }.resume()

    NSLog("Got here 4?")
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

Le code ci-dessus génère le résultat suivant:

2016-10-04 13:00:12.011969 OneTouch[1589:623015] [DYMTLInitPlatform] platform initialization successful
2016-10-04 13:00:12.264319 OneTouch[1589:622954] [MC] System group container for systemgroup.com.Apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.Apple.configurationprofiles
2016-10-04 13:00:12.265321 OneTouch[1589:622954] [MC] Reading from public effective user settings.
2016-10-04 13:00:12.295055 OneTouch[1589:622954] Got here?
2016-10-04 13:00:12.295445 OneTouch[1589:622954] Got here 4?
2016-10-04 13:00:12.295515 OneTouch[1589:622954] End of getUser
(lldb) 

Ce qui signifie que la demande n'est même pas faite. Y at-il une clé que je dois ajouter à la PLIST à nouveau? Cela commence à devenir ennuyeux.

Ci-dessous mon ancien code et il ne fonctionne même plus:

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    let request = NSMutableURLRequest(url: URL(string: "http://domain.tld/path/" as String)!, cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 20)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    NSLog("Got here?")

    let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {data, response, error in
        if error != nil {
            NSLog("Got here 2?")
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data!)

        NSLog("Object: \(object)")
    })

    NSLog("Got here 4?")

    task.resume()
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

Le code ci-dessus donne la même sortie que l'autre code!

8
recoilnetworks

Si vous placez un point d'arrêt immédiatement après avoir appelé getUser, le gestionnaire d'achèvement de la tâche URLSession, qui s'exécute de manière asynchrone (c'est-à-dire se termine généralement plus tard, à moins que la demande n'échoue immédiatement ou qu'elle ne soit pas satisfaite par une réponse mise en cache).

Si vous placez un point d'arrêt dans le gestionnaire d'achèvement dataTask, vous devriez voir vos données à cet endroit.


Personnellement, je m'assurerais de donner à getUser un gestionnaire de complétion afin que vous sachiez quand c'est fait:

func getUser(completionHandler: @escaping (JSON?, Error?) -> Void) {
    let params = [
        "email":"\(preferences.string(forKey: "preference_email")!)"
    ]

    let requestParams: [String: Any] = [
        "action": "601",
        "params": params
    ]

    do {
        let requestObject = try JSONSerialization.data(withJSONObject: requestParams)

        var request = URLRequest(url: URL(string: "http://domain.tld/path/")!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20)

        request.httpBody = requestObject
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) {data, response, error in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }

            completionHandler(JSON(data: data), nil)
        }

        task.resume()
    } catch {
        completionHandler(nil, error)
    }
}

Ensuite, lorsque vous appelez cela, vous pouvez faire quelque chose comme:

getUser { json, error in
    guard let json = json else {
        print(error)
        return
    }

    // do something with json
    print(json)
}

Et placez simplement votre point d'arrêt dans le gestionnaire d'achèvement de getUser. Et rappelez-vous que vous n'avez aucune assurance que le gestionnaire d'achèvement s'exécutera sur la file d'attente principale ou non. Vous devez donc vous assurer de répartir les mises à jour de l'interface utilisateur ou du modèle dans la file d'attente principale.

0
Rob