我正在学习swift并尝试实现一个函数来下载返回NSData类型,同时还将它保存到类中的另一个变量。
我希望答案能够从根本上改变下面解释的代码,因为这就是我们现在被告知要做的事情。
我无法确定在dispatch_async()函数中正确返回新下载的NSData类型的位置,并且假设它在后台下载,该函数返回的时间早于下载,因此调用函数看到它返回零...
这是我的课程(简化) -
class Photo {
var title : String
var url : String
var data : NSData? = nil
func imageData(newUrl: String? = nil) -> NSData? {
/// Check if the current Photo object has either:
/// - No data cached -OR-
/// - The URL differs from newUrl variable
if self.data == nil || (newUrl != nil && newUrl != self.url) {
if let url = NSURL(string: self.url) {
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
// Asyncronous block
dispatch_async(queue) {
if let newData = NSData(contentsOfURL: url) {
let mainQueue = dispatch_get_main_queue()
dispatch_async(mainQueue, {
self.data = newData // Cache data
})
} else {
print("Could not download image: '\(self.url)'")
self.data = nil
}
}
}
}
return self.data
}
} // End class
答案 0 :(得分:1)
实现此目的的一种方法是实施completion handler。简单地说,你实际上并没有从函数中返回任何内容,只是将任何数据传递给完成处理程序,然后调用其他地方定义的处理程序。
在您的示例中,您可以将函数定义更改为func imageData(newUrl: String? = nil, completion: (data: NSData?) -> Void)
。您现在已经定义了一个名为completion
的完成处理程序(闭包),其data
参数和返回类型Void
。然后,您可以在此块中定义处理此函数的处理程序,如下所示:
imageData("someurl") { (data) in
print(data)
}
这只是将数据打印到控制台,但您可以使用此数据执行任何操作。
完整代码:
func imageData(newUrl: String? = nil, completion: (data: NSData?) -> Void) {
/// Check if the current Photo object has either:
/// - No data cached -OR-
/// - The URL differs from newUrl variable
if self.data == nil || (newUrl != nil && newUrl != self.url) {
if let url = NSURL(string: self.url) {
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
// Asyncronous block
dispatch_async(queue) {
if let newData = NSData(contentsOfURL: url) {
let mainQueue = dispatch_get_main_queue()
dispatch_async(mainQueue, {
self.data = newData // Cache data
// pass data to the completion block
completion(data: self.data)
})
} else {
print("Could not download image: '\(self.url)'")
self.data = nil
}
}
}
} else {
// pass data to the completion block
completion(data: self.data)
}
}
还有其他方法可以实现这一点,但我认为这将是最简单的代码更改。您可以查看的其他方式是使用代理NSNotification
或NSOperation
。有关详情,请参阅以下教程:http://www.appcoda.com/ios-concurrency/,https://www.raywenderlich.com/79149/grand-central-dispatch-tutorial-swift-part-1,https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift