我想创建一个从url加载数据然后将responseData作为NSData返回的函数.我想阻止mainThread直到数据完成.这是我到目前为止:
功能:
typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
func requestURL(targetUrl: String, httpMethod: String, httpBody: String, completion: CompletionBlock){
// REQUEST
let target = NSURL(string: targetUrl) // URL
let request = NSMutableURLRequest(URL: target!) // REQUEST
// HTTP-METHOD
var method = httpMethod
if method != "POST" { method = "GET" } // STANDARD: GET
request.HTTPMethod = method
// HTTP-BODY
let body = httpBody
if body != "" {
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
}
// NSURLSession
let session = NSURLSession.sharedSession()
let task = …Run Code Online (Sandbox Code Playgroud) 我将一些函数链接在一起,一旦所有函数都运行完毕,我无法弄清楚如何使用返回值调用完成处理程序。
func getAirQuality(completion: (aqi: Int?) -> Void) {
callAPI()
}
private func callAPI() {
// ... get data
self.parseDataForAQI(data: data)
}
private func parseDataForAQI(data: Data) {
let aqi = aqi
// Send aqi up to completion handler in getAirQuality
}
Run Code Online (Sandbox Code Playgroud)
所以当一切都说完后,我可以做这样的事情:
getAirQuality(completion: { aqi -> Void in {
// Do something with aqi
})
Run Code Online (Sandbox Code Playgroud) 当前,我有一个完成处理程序:
open func Start(completion: (() -> Void)) { ... }
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我必须始终致电completion。我怎样才能使它成为可选的,所以在某些方法中我将使用completion块,而在另一些方法中,我将跳过它们而不添加到我的方法调用中?
例如,我想要与以下内容相同:
self.present(<#T##viewControllerToPresent: UIViewController##UIViewController#>, animated: <#T##Bool#>, completion: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
Run Code Online (Sandbox Code Playgroud)
我试过了
open func Start(completion: (() -> Void)? = nil) { ... }
Run Code Online (Sandbox Code Playgroud)
添加问号,但是在这种情况下,我必须调用可选的完成块
completion?()
Run Code Online (Sandbox Code Playgroud)
我不能简单地打电话
start()
Run Code Online (Sandbox Code Playgroud)
我不需要在完成块中。需要我叫它
我目前正在 Xcode 10 Playground (Swift 5) 中测试此代码:
func one() {
let test = "bla"
two(test, completion: { (returned) in
print(returned)
})
}
func two(_ test: String, completion: @escaping (_ returned: String?) -> Void) {
DispatchQueue.global(qos:.background).async {
if !test.isEmpty {
//Some slow stuff
DispatchQueue.main.async {
return completion("hi!")
}
}
//Also some slow stuff
DispatchQueue.main.async {
return completion(nil) //can't have this in "else"!
}
}
}
one()
Run Code Online (Sandbox Code Playgroud)
问题是“hi”和“nil”都被打印了。
如果我摆脱线程,它工作得很好,但有了它,它似乎在DispatchQueue.main.async第一个线程有机会返回之前到达第二个线程。
在我的实际代码中的“一些缓慢的东西”中还有很多事情发生,if但我不能依赖在调用第二次返回之前花费足够长的时间来返回。
如何实现这一点:让函数在后台线程中运行,但在主线程上仅返回一次(就像通常没有线程的代码一样)?
ios completionhandler swift ios-multithreading dispatch-queue
我创建了下面这两种方法来注销用户。当 logout2(...) 被调用时,用户可以在 logout1() 运行之前在 anyFinalChanges 中进行任何更改。
private func logout1() {
Cache.clearCache()
}
func logout2(anyFinalChanges: () -> (), userLoggedOut: () -> ()) {
anyFinalChangesInThisClosure()
logout()
userLoggedOut()
}
Run Code Online (Sandbox Code Playgroud)
当我实现注销方法时,第二个闭包不显示名称
.logOut2(anyFinalChanges: {
}) { //No Name here.. why is that?
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能使闭包的名称始终出现?