URLSessionUploadTask obtenir automatiquement annulée instantanément
Je vais avoir cette étrange question qui vient d'être créée URLSessionUploadTask
est annulé instantanément. Je ne suis pas sûr si c'est un bug avec la version bêta actuelle de Xcode 8.
Je le soupçonne peut-être un bug, car le code je suis sur le point de publier fonctionnait bien exactement une fois. Aucune modification n'a été apportée par la suite et puis il a tout simplement cessé de fonctionner. Oui, elle a littéralement couru une fois, puis il a cessé de travailler. Je vais poster l'erreur vers la fin.
Je vais poster le code ci-dessous, mais je vais d'abord résumer la logique ici.
Mon test, l'utilisateur ou exposés API (c'est à dire pour une utilisation dans les cours de récréation ou directement sur apps), appelle la authorize
méthode. Cette authorize
méthode est à son tour appel buildPOSTTask
, qui permettra de construire une URL valide et retourner un URLSessionUploadTask
à être utilisé par le authorize
méthode.
Avec qui a déclaré, le code est ci-dessous:
La session:
internal let urlSession = URLSession(configuration: .default)
Fonction pour créer une importation de tâche:
internal func buildPOSTTask(onURLSession urlSession: URLSession, appendingPath path: String, withPostParameters postParams: [String : String]?, getParameters getParams: [String : String]?, httpHeaders: [String : String]?, completionHandler completion: URLSessionUploadTaskCompletionHandler) -> URLSessionUploadTask {
let fullURL: URL
if let gets = getParams {
fullURL = buildURL(appendingPath: path, withGetParameters: gets)
} else {
fullURL = URL(string: path, relativeTo: baseURL)!
}
var request = URLRequest(url: fullURL)
request.httpMethod = "POST"
var postParameters: Data? = nil
if let posts = postParams {
do {
postParameters = try JSONSerialization.data(withJSONObject: posts, options: [])
} catch let error as NSError {
fatalError("[\(#function) \(#line)]: Could not build POST task: \(error.localizedDescription)")
}
}
let postTask = urlSession.uploadTask(with: request, from: postParameters, completionHandler: completion)
return postTask
}
La fonction d'authentification, qui utilise une tâche créée par la fonction ci-dessus:
public func authorize(withCode code: String?, completion: AccessTokenExchangeCompletionHandler) {
//I have removed a lot of irrelevant code here, such as the dictionary building code, to make this snippet shorter.
let obtainTokenTask = buildPOSTTask(onURLSession: self.urlSession, appendingPath: "auth/access_token", withPostParameters: nil, getParameters: body, httpHeaders: nil) { (data, response, error) in
if let err = error {
completion(error: err)
} else {
print("Response is \(response)")
completion(error: nil)
}
}
obtainTokenTask.resume()
}
J'ai rattrapé cette erreur dans un test:
let testUser = Anilist(grantType: grant, name: "Test Session")
let exp = expectation(withDescription: "Waiting for authorization")
testUser.authorize(withCode: "a valid code") { (error) in
if let er = error {
XCTFail("Authentication error: \(er.localizedDescription)")
}
exp.fulfill()
}
self.waitForExpectations(withTimeout: 5) { (err) in
if let error = err {
XCTFail(error.localizedDescription)
}
}
Il échoue toujours instantanément avec cette erreur:
Erreur de Domaine=NSURLErrorDomain Code=-999 "annulé" UserInfo={NSErrorFailingURLKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED,
NSLocalizedDescription=annulé,
NSErrorFailingURLStringKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED}
Voici quelques choses à garder à l'esprit:
- L'URL utilisée par la session est valide.
- Toutes les informations d'identification sont valides.
- Il échoue instantanément avec un "annulé" erreur, qui n'a tout simplement pas se produire avant. Je ne suis pas annuler la tâche n'importe où, donc, c'est d'être annulées par le système.
- Il échoue également sur les aires de jeux avec indéterminée exécution activé. Ce n'est pas limité à mes tests.
Voici une liste de choses que j'ai essayé:
- Parce que j'ai l'impression que c'est un bug, j'ai d'abord essayé de nettoyer mon projet, de supprimer des données dérivées, et de réinitialiser tous les simulateurs. Aucun d'entre eux travaillaient.
- Est même allé aussi loin de redémarrer mon Mac...
- Sous le petit soupçon que l'importation de tâche a été d'obtenir libéré à cause d'elle de ne pas en avoir de fortes présomptions, et à son tour l'appel de
cancel
, j'ai également réécritauthorize
de retourner à la tâche créée parbuildPOSTTask
et affecté à une variable dans mon test. La tâche était encore en train annulé.
Choses que je n'ai pas encore essayer (mais j'accepte toutes les autres idées que je travail à travers ces):
- L'exécuter sur un périphérique physique. En cours de téléchargement iOS 10 sur un iPad que c'est un iOS du projet 10. EDIT: je viens d'essayer et il n'est pas possible de le faire.
Je suis à court d'idées de ce à essayer. Les journaux générés ne semblent pas avoir toutes les infos utiles.
EDIT:
J'ai décidé de publier la totalité du projet ici. La chose sera open source, de toute façon quand c'est fini, et l'API informations d'identification que je possède sont pour une application de test.
- Bon, désolé, devinez qui est important, haha. Ouais le test n'ont waitForExpectationsWithTimeout appel. Je vais modifier ma question à rajouter. Je n'ai pas essayé dans une application réelle encore (c'est un cadre que je suis en train de construire, mais une application qui consomme sera construit peu de temps après), mais elle ne parviennent pas rapidement aire de jeux avec indéterminée exécution activé.
- Pouvez-vous essayer: pastebin.com/B7nZFY1n T-il imprimer la réponse? Donne une erreur?
- Merci pour vos commentaires Brandon. J'ai couru sur un terrain de jeu et il a bien fonctionné. Imprimé de la réponse comme prévu.
- Écrire un test pour le code que vous m'avez donné fonctionne très bien. Quelque chose doit se passer entre mes appels de méthode.
- pastebin.com/ijshDH6Q Semble être le même code que vous utilisez. J'ai pu en déduire sur la base de votre code d'erreur.
- Je suis juste allé à
buildPOSTTask
et codés en dur le StackOverflow URL-il. Ainsi, au lieu devar request = URLRequest(url: fullURL)
, j'ai euvar request = URLRequest(url: URL(string: "http://www.stackoverflow.com")!)
. Il n'a toujours pas. C'est aussi ne pas trop tôt, il n'a pas vraiment l'impression qu'elle arrive à faire la demande. J'ai juste essayé de le faire dans la cour de récréation, et a également été annulé il.
Vous devez vous connecter pour publier un commentaire.
Après avoir lutté non-stop avec cette pendant 6 jours, et après googler non-stop pour une solution, je suis vraiment heureux de dire que j'ai enfin compris.
Tourne notre que, pour quelque mystérieuse raison, la
from:
paramètre dansuploadTask(with:from:completionHandler)
ne peut pas être nul. Malgré le fait que le paramètre est marqué comme une option deData
, il est annulé immédiatement quand il est absent. C'est probablement un bug sur l'Apple côté, et j'ai ouvert un bug quand je ne pouvais pas obtenir que cela fonctionne, je vais donc mettre à jour mon rapport de bug avec cette nouvelle information.Avec cela dit, tout ce que j'avais à faire était de mettre à jour mon
buildPOSTTask
méthode pour tenir compte de la possibilité du passé de dictionnaire à néant. Avec cela en place, il fonctionne très bien maintenant:Votre serveur est cassé..
Il attend infiniment pour "écrit" pour terminer..
Il envoie la demande.. est-ce que le SSL handshake et n'obtient pas de réponse. Il expire et la considère comme une fracture de la demande..
fullURL
dansbuildPOSTTask
avechttp://www.stackoverflow.com
ethttps://www.google.com
et la même chose se passe. Le code que vous avez fournis dans cette réponse se termine avec succès dans une Aire de jeu, et je suis en mesure de voir la réponse (pour la Anilist URL). Il ne semble pas que le serveur est cassé (je ne le gèrent pas d'ailleurs), et il n'y a pas eu de rapports de personnes qui ont des problèmes d'autoriser des applications. Ceci est source de confusion, je vais l'essayer dans une application réelle pour voir comment il va.is waiting for writes to complete so it can determine if new data is available
chose ne semble pas avoir quelque chose à voir avec la requête elle-même. Il semble faire partie de certains agressif de la journalisation dans le courant des versions bêta. Je n'ai pu trouver ceci, mais vous pouvez le voir, ils ne sont même pas à l'aide de URLSession ou équivalent Api.is waiting for writes to complete so it can determine if new data is available
l'exploitation forestière comme dénuée de sens. Je vous remercie pour vos commentaires si. Vont essayer de comprendre quel est le problème.Êtes-vous, par hasard, à l'aide d'un tiers bibliothèque comme Ensighten? J'ai eu exactement le même problème dans XCode beta 8 (fonctionne très bien dans XCode 7) et tous mes blocs à néant les paramètres étaient à l'origine des accidents. Il s'avère que c'était la bibliothèque à faire certains de codage à l'origine du problème.