我正在使用闭包编写Swift函数。应该是可编译的代码示例是这样的,
import Foundation
typealias PKSynchronizeProgressBlock = (Double) -> Void
typealias PKSynchronizeCompletionBlock = (Bool, NSError?) -> Void
class X {
func synchronizeAppDataWithProgress(
progress: PKSynchronizeProgressBlock?,
completion: PKSynchronizeCompletionBlock?) {
dispatch_async(dispatch_get_main_queue(), {
// Do a lot of downloading, and during the process
// {
// If progress is updated
if (progress != nil) {
progress!(Double(0))
}
//
// If something goes wrong
if (completion != nil) {
completion!(false, nil)
}
// }
dispatch_async(dispatch_get_main_queue(), {
if (completion != nil) {
completion!(true, nil)
}
})
})
}
func foo() {
self.synchronizeAppDataWithProgress({ (progress: Double) -> Void in
self.launchProgressBar.progress = progress
}, completion: { (success: Bool, error: NSError?) -> Void in
if success {
self.launchProgressBar.progress = 1.0
}
else {
print("Failed to synchronize app data with error %@", error!)
}
})
}
}
但是,此代码无法编译。 Xcode说
无法调用" synchronizeAppDataWithProgress'带参数列表 '(进度:(双倍) - >无效,完成:( Bool,NSError?) - > Void)'
我该怎么办?我的代码中是否犯了任何愚蠢的错误?
更新
感谢@Mario Zannone。我修复了上面代码中的前两个错误。那是:(1)我在函数调用中插入了一个冗余的progress:
。我删除了那个。 (2)我在主线程以外的线程中更新了UI。
但是,如果我不在foo()
注释掉以下单行,那么代码仍然不起作用,
self.launchProgressBar.progress = progress
你有什么线索吗?
答案 0 :(得分:0)
Xcode有时会挑剔,因为参数在闭包中列出。我发现最好留下推断的类型。还要确保使用捕获列表来避免闭包中的强引用周期。
使用Alamofire依赖项,我已经重写了上面的代码并进行了编译。
import Alamofire
typealias ProgressBlock = (Double) -> Void
typealias CompletionBlock = (Bool, ErrorType?) -> Void
class ExampleDataSource {
func fetchData(progress: ProgressBlock?, completion: CompletionBlock?) {
// Here we use the Alamofire Dependency for progress reporting simplicity.
Alamofire.request(.GET, "https://www.myexampledomain.com")
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
// bytesRead, totalBytesRead, and totalBytesExpectedToRead are Int64
// so we must perform unit conversion
let progressPercentage = Double(totalBytesRead) / Double(totalBytesExpectedToRead)
// here we optionally call the ProgressBlock 'progress' and pass it the progressPercentage
progress?(progressPercentage)
}
.response { request, response, data, error in
// here we usually parse the data, but for simplicity we'll
// simply check to see if it exists.
let completionFlag = (data != nil)
// note that NSError? is interchangable with ErrorType?
completion?(completionFlag, error)
}
}
func performTasks() {
// first we'll set up our closures...
let progressBlock: ProgressBlock = { progress in
// here we update the UI or whatever
// the nice thing about the Alamofire dependency is
// that it's thread-safe :]
}
let completionBlock: CompletionBlock = { success, error in
// here we do whatever we need to do when the
// network operation finishes, or handle the
// errors appropriately
}
// then we'll pass them into our fetchData method
fetchData(progressBlock, completion: completionBlock)
}
}