我希望在长期操作完成后返回一些值。 但此外,我想分裂逻辑和gui。
例如;我有两个班级
所以,以前在Objective-C中我只是在SomeServices中添加一个方法:
(void)getDataFromService:(void (^)(NSArray *, NSError *))completionBlock{ ...... }
在这个方法中,我刚刚调用completionBlock(myData, myError)
将我的值返回到tableviewcontroller。
我必须在SomeServices.swift中定义的等效闭包是什么以及如何在MyTableViewController中调用它?
我知道如何调用这样的简单闭包:
....({
responseData, error in
if(!error){
//Do something
}
})
但我没有任何想法如何定义一个与completionBlock等效的闭包。
任何帮助将不胜感激
答案 0 :(得分:14)
关闭的好处是,你可以传递你想要的一切。方法或功能 - 它并不重要。
您可以在参数中传递一个函数,然后调用它。
func someFunctionThatTakesAClosure(completionClosure: () -> ()) {
// function body goes here
if(error = false) {
completionClosure()
}
}
//Call it
someFunctionThatTakesAClosure({
//Completions Stuff
println("someFunctionThatTakesAClosure")
});
摘自:Apple Inc.“The Swift Programming Language。”iBooks。 https://itun.es/ch/jEUH0.l
答案 1 :(得分:3)
答案在语言指南中:
假设您要返回一个String。这是语法
({(responseData: DataClass, error: ErrorClass) -> String in
//do stuff - calculations etc..
return calculatedString
})
这是一个示例,它接受两个字符串并连接它们,并返回结果:
let sumStrings = ({(first: String, second: String) -> String in
return first + " " + second
})
然后您可以执行以下操作:
sumStrings("Hello","Swift") // "Hello Swift"
答案 2 :(得分:1)
以下是我使用单例ServiceManager实现此目的的方法。
class ServiceManager: NSObject {
// Static Instance variable for Singleton
static var sharedSessionManager = ServiceManager()
// Function to execute GET request and pass data from escaping closure
func executeGetRequest(with urlString: String, completion: @escaping (Data?) -> ()) {
let url = URL.init(string: urlString)
let urlRequest = URLRequest(url: url!)
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
// Log errors (if any)
if error != nil {
print(error.debugDescription)
} else {
// Passing the data from closure to the calling method
completion(data)
}
}.resume() // Starting the dataTask
}
// Function to perform a task - Calls executeGetRequest(with urlString:) and receives data from the closure.
func downloadMovies(from urlString: String, completion: @escaping ([Movie]) -> ()) {
// Calling executeGetRequest(with:)
executeGetRequest(with: urlString) { (data) in // Data received from closure
do {
// JSON parsing
let responseDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
if let results = responseDict!["results"] as? [[String:Any]] {
var movies = [Movie]()
for obj in results {
let movie = Movie(movieDict: obj)
movies.append(movie)
}
// Passing parsed JSON data from closure to the calling method.
completion(movies)
}
} catch {
print("ERROR: could not retrieve response")
}
}
}
}
下面是我如何使用单例类的示例。
ServiceManager.sharedSessionManager.downloadMovies(from: urlBase) { (movies : [Movie]) in // Object received from closure
self.movies = movies
DispatchQueue.main.async {
// Updating UI on main queue
self.movieCollectionView.reloadData()
}
}
我希望这可以帮助任何人寻找相同的解决方案。