Je suis confus quant à la syntaxe d'un gestionnaire d'achèvement dans Swift 3.
Dans la fonction ci-dessous, après l'analyse d'un fichier xml
à partir d'un appel de service Web, il devrait renvoyer une variable (un array [String:String]
).
Ma tentative est en dessous, mais évidemment, elle est incorrecte.
enum HistoryKey {
case success([String:String])
case failure(String)
}
private func getHistoryKeys(searchterm: String, completion: @escaping () -> HistoryKey) {
let url = PubmedAPI.createEsearchURL(searchString: searchterm)
let request = URLRequest.init(url: url as URL)
let task = session.dataTask(with: request) { (data, response, error) in
if let theData = data{
let myParser = XMLParser.init(data: theData)
myParser.delegate = self
myParser.parse()
}
}
task.resume()
if keys.isEmpty {
return .failure("no historyKeyDictionary")
}else{
return .success(keys)
}
}// End of func
Je veux utiliser cette fonction comme suit
let result = self.getHistoryKeys(searchTerm)
Deux problèmes:
HistoryKey
et n'a pas de valeur de retour. La signature doit donc être l'inverse.Pour pouvoir analyser les données reçues en dehors du bloc d'achèvement, renvoyez la variable data
en cas de succès.
enum ConnectionResult {
case success(Data)
case failure(Error)
}
private func getHistoryKeys(searchterm: String, completion: @escaping (ConnectionResult) -> ()) {
let url = PubmedAPI.createEsearchURL(searchString: searchterm)
let task = session.dataTask(with: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
} else {
completion(.success(data!))
}
}
task.resume()
}
et l'appelle
getHistoryKeys(searchterm: String) { connectionResult in
switch connectionResult {
case .success(let data):
let myParser = XMLParser(data: data)
myParser.delegate = self
myParser.parse()
// get the parsed data from the delegate methods
case .failure(let error): print(error)
}
}
Vous n'utilisez pas le bloc completion
.
Utilisez-le comme:
private func getHistoryKeys(searchterm: String, completion: @escaping (_ keys: Array) -> Void) {
//do the magic
completion(keys)
}
Ensuite, vous pouvez appeler cette fonction en tant que:
getHistoryKeys(searchterm: "str") { (keys) in
print("\(keys)")
}
Renvoie le résultat sous forme d'argument dans le gestionnaire d'achèvement:
private func getHistoryKeys(searchterm: String, completion: @escaping (result: HistoryKey) -> Void) {
let url = PubmedAPI.createEsearchURL(searchString: searchterm)
let request = URLRequest.init(url: url as URL)
let task = session.dataTask(with: request) { (data, response, error) in
if let theData = data{
let myParser = XMLParser.init(data: theData)
myParser.delegate = self
myParser.parse()
}
//DispatchQueue.main.async { // if you want to do UI stuff dispatch calls to completion() on the main queue
if keys.isEmpty {
completion(.failure("no historyKeyDictionary"))
} else{
completion(.success(keys))
}
//}
}
task.resume()
}
Et appelez ça comme ça:
getHistoryKeys("searchMe") { (result: HistoryKey) in
print(result)
}
D'après ce que je peux voir, cela devrait être
private func getHistoryKeys(searchterm: String, completion: @escaping (HistoryKey) -> ())
De plus, completion(.failure("no historyKeyDictionary"))
ou completion(.success(keys))
doit être utilisé à la place de return
Swift 4.2
enum HistoryKey {
case success([String:String])
case failure(String)
}
func myFunction(str: String, completionHandler: @escaping (HistoryKey) -> ()){
completion(.success([String:String]))
//OR
completion(.failure(""))
}
myFunction(str: String) { result in
switch result {
case .success(let data): break;
case .failure(let error): break;
}
}
OU
func myFunction(str: String, completionHandler: @escaping (String) -> ()){
completionHandler("")
}
myFunction(str: "someThing", completionHandler: {(str) in
})
enum HistoryKey {
case success([String: String])
case failure(String)
}
private func getHistoryKeys(searchterm: String, completion: @escaping (_ result: HistoryKey) -> Void) {
let url = PubmedAPI.createEsearchURL(searchString: searchterm)
let request = URLRequest.init(url: url as URL)
let task = session.dataTask(with: request) { (data, response, error) in
if let theData = data{
let myParser = XMLParser.init(data: theData)
myParser.delegate = self
myParser.parse()
}
if keys.isEmpty {
completion(.failure("no historyKeyDictionary"))
} else {
completion(.success(keys))
}
}
task.resume()
} // End of func
Quelque chose comme ca. Modifiez la déclaration @escaping
et complétez la déclaration au lieu de la renvoyer.
J'espère que ça aide.