完成处理程序 swift 3 从函数返回一个变量
Posted
技术标签:
【中文标题】完成处理程序 swift 3 从函数返回一个变量【英文标题】:Completion handler swift 3 return a variable from function 【发布时间】:2017-05-23 10:02:38 【问题描述】:我对 swift 3 中完成处理程序的语法感到困惑。
在下面的函数中,从 Web 服务调用解析 xml
文件后,它应该返回一个变量(array [String:String]
)。
我的尝试如下,但显然是不正确的。
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
我想使用这个功能如下
let result = self.getHistoryKeys(searchTerm)
【问题讨论】:
@EricAya 他没有尝试从函数返回值,而是将其传递给另一个完成处理程序。 您的权利。我没有注意到这一点。 @EricAya 请采纳答案,让其他人更快找到。谢谢。按寒鸦 【参考方案1】:两个问题:
完成处理程序传递一个HistoryKey
实例并且没有返回值,因此签名必须相反。
完成处理程序的调用必须在数据任务的完成块内。
为了能够在完成块之外解析接收到的数据,成功时返回data
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()
并称之为
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)
【讨论】:
抱歉,我刚刚添加了一个编辑,以说明我想如何使用该功能。您的解决方案适用于上述情况吗? 不,它没有。要么您必须返回收到的Data
,因为解析器异步工作并在函数外部解析 XML,或者您必须将完成处理程序分配给一个变量以获得强引用并从 XMLParser 委托方法调用完成处理程序。顺便说一句:枚举情况下的 array 是字典。
PS:我更新了答案以在完成处理程序中传递接收到的数据。将处理 XML 解析器结果的代码放入解析器委托方法中。
我了解您的解决方案 - 从委托方法获取变量,例如 parserDidEndDocument。但是,你能告诉我如何从 parserDidEndDocument 调用完成处理程序吗?【参考方案2】:
您没有使用completion
块。
像这样使用它:
private func getHistoryKeys(searchterm: String, completion: @escaping (_ keys: Array) -> Void)
//do the magic
completion(keys)
那么你可以调用这个函数为:
getHistoryKeys(searchterm: "str") (keys) in
print("\(keys)")
【讨论】:
【参考方案3】:斯威夫特 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;
或
func myFunction(str: String, completionHandler: @escaping (String) -> ())
completionHandler("")
myFunction(str: "someThing", completionHandler: (str) in
)
【讨论】:
【参考方案4】:在完成处理程序中将结果作为参数返回:
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()
然后这样称呼它:
getHistoryKeys("searchMe") (result: HistoryKey) in
print(result)
【讨论】:
抱歉,我刚刚添加了一个编辑,以说明我想如何使用该功能。您的解决方案适用于上述情况吗?因为你的返回值是 void 没有。self.getHistoryKeys(searchTerm)
立即返回,但您的下载需要时间。你必须等待它。【参考方案5】:
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
类似的东西。更改@escaping
声明并完成而不是返回。
希望对你有帮助。
【讨论】:
【参考方案6】:据我所见,应该是
private func getHistoryKeys(searchterm: String, completion: @escaping (HistoryKey) -> ())
还应使用completion(.failure("no historyKeyDictionary"))
或completion(.success(keys))
而不是return
【讨论】:
以上是关于完成处理程序 swift 3 从函数返回一个变量的主要内容,如果未能解决你的问题,请参考以下文章