Swift闭包:无法使用参数列表

时间:2015-07-26 12:12:52

标签: ios swift closures

我正在使用闭包编写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

你有什么线索吗?

1 个答案:

答案 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)
    }
}