【发布时间】:2014-07-17 00:09:19
【问题描述】:
我正在尝试编写一个执行异步 GET 请求并返回响应的函数(作为任何数据类型,但这里是作为 NSData)。
本题基于:How to use NSURLConnection completionHandler with 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
}
但我得到一个错误:
error: variable 'dataOutput' captured by a closure before being initialized
我已经尝试从completionHandler返回值,但它需要一个void返回,这让我想起了我希望在没有帮助的情况下解决这个问题......:D
我看过: How to use completionHandler Closure with return in Swift? 但这并不能真正回答我的问题。我的目标是从我的异步请求中获取数据,以便在我的代码中的其他地方使用。我是否应该在这个块中完成这个请求的所有工作,而不是把数据取出来?
谢谢!
编辑
好的,所以我有一个我认为可能可行的选项,但对我来说似乎不合适。谁能告诉我这是否是实现目标的最佳方式?
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)
})
}
EDIT 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)
}
}
感谢您花时间回答我的问题。我是 swift 新手,堆栈溢出非常有用!
【问题讨论】:
-
var dataOutput: NSData!怎么样? -
当我使用
var dataOutput: NSData!时,我收到以下错误:fatal error: unexpectedly found nil while unwrapping an Optional value。我觉得这可能是因为它是一个异步请求,并且没有立即返回值。这让我相信我的第二次编辑可能是更好的选择 -
但很高兴知道!是否简单地隐式展开变量允许在嵌套函数中访问它?当我看到你的回复时,我捂住了脸:D
-
异步做事时,不能同步返回。所以你应该喜欢你的第二次编辑。使用 optional 可以让您跳过初始化,因为编译器将使用 nil 静默初始化。您可以初始化变量,而不是使用可选的,但在您的情况下,使用空数据进行初始化是浪费的。
标签: swift closures nsurlrequest completionhandler