cos*_*olf 13 closures nsurlrequest completionhandler swift
我正在尝试编写一个将执行异步GET请求的函数,并返回响应(作为任何数据类型,但在这里它是NSData).
这个问题基于:如何使用NSURLConnection completionHandler和swift
func getAsynchData() -> NSData {
var dataOutput : NSData
let url:NSURL = NSURL(string:"some url")
let request:NSURLRequest = NSURLRequest(URL:url)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
/* this next line gives the below error */
dataOutput = data
})
return dataOutput
}
Run Code Online (Sandbox Code Playgroud)
但是我收到一个错误:
error: variable 'dataOutput' captured by a closure before being initialized
Run Code Online (Sandbox Code Playgroud)
我已经尝试从completionHandler返回值,但它需要一个void返回,这让我想起了我希望在没有帮助的情况下解决这个问题......:D
我看过: 如何在Swift中使用completionHandler Closure返回? 但这并没有真正回答我的问题.我的目标是从我的异步请求中获取数据,以便在我的代码中的其他地方使用.我是否应该在此块中执行此请求的所有工作而不是获取数据?
谢谢!
编辑
好的,所以我有一个选项,我觉得可能有用,但对我来说似乎不对.有人能告诉我这是否是实现目标的最佳方式?
func doThingsWithData( data: NSData ) -> String {
/* code to extract string from NSData */
return somestring
}
func getAsynchData() {
let url:NSURL = NSURL(string:"some url")
let request:NSURLRequest = NSURLRequest(URL:url)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
/* this next line gives the below error */
doThingsWithData(data)
})
}
Run Code Online (Sandbox Code Playgroud)
编辑2 - >响应撤消
谢谢,撤消.你的回答对我有意义.这里有更多的谜题.我有一个类是我的API处理程序.我希望能够实例化该类,并在其上调用函数以从API获取数据.我宁愿让所有的数据和一个API调用,而不是进行单独的呼叫,每次每个我需要走出价值,作为一个单一的API调用包含了所有我需要的数据,但可能是一个整体的其他答案.这是代码:
class GetInfoFromAPI {
func getSpecificValue(index : String) -> String {
/* I assume I need to send the values from this function, yea? but how do I get them here? */
}
func doThingsWithData( data: NSData ) -> String {
/* code to extract string from NSData */
var error: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as NSDictionary
specificValue1 : String = jsonDict.valueForKey("value1") as String
specificValue2 : String = jsonDict.valueForKey("value2") as String
specificValue3 : String = jsonDict.valueForKey("value3") as String
/* I want to get these ^^^ values into the ViewController below */
}
func getAsynchData() {
let url:NSURL = NSURL(string:"some url")
let request:NSURLRequest = NSURLRequest(URL:url)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
/* this next line gives the below error */
doThingsWithData(data)
})
}
}
class ViewController: UIViewController {
@IBOutlet var labelVariable1: UILabel
@IBOutlet var labelVariable2: UILabel
@IBOutlet var labelVariable3: UILabel
let apiInstance = GetInfoFromAPI()
@IBAction func buttonTapped(sender : AnyObject) {
labelVariable1 = apiInstance.getSpecificValue(1)
labelVariable2 = apiInstance.getSpecificValue(2)
labelVariable3 = apiInstance.getSpecificValue(3)
}
}
Run Code Online (Sandbox Code Playgroud)
感谢您抽出宝贵时间回答我的问题.我是swift的新手,堆栈溢出非常有用!
让我试着解释一下 - 这是对线程的误解,我自己一开始就在努力解决.我将尝试简化一些事情.当您运行此代码时:
NSLog("Log 1")
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
NSLog("Log in Completion Block")
})
NSLog("Log after request")
Run Code Online (Sandbox Code Playgroud)
您将获得如下所示的输出:
Log 1
Log after request
Log in completion block
Run Code Online (Sandbox Code Playgroud)
让我制作一张图表,一种时间表:
"Log 1" (before request is sent)
|
|
Request sent over Internet
|
/ \
"Log after request" |
This is logged *before* |
the other one, because this |
one doesn't have to wait for |
the network to respond. |
|
The method finishes and returns a value. |
------------------------------------------------------------------------------
| The network finally responds,
| and the completion block is run.
|
"Log in completion block"
Run Code Online (Sandbox Code Playgroud)
垂直线是方法完成并返回的位置.在所有情况下,您的方法在运行完成块之前已经向其调用者返回了一个值.你无法线性地思考这个问题.
我是否应该在此块中执行此请求的所有工作而不是获取数据?
是的,基本上.如果你向我展示getAsynchData()首先调用的代码,我可以提供更多帮助.