我有一个按钮,它通过segue将视图控制器连接到另一个视图控制器,按下时,将text
作为参数从UITextField
发送到AFNetwork
POST
请求,并且必须根据请求是否成功来决定segue是否可以继续。
所以我写了这个:
var proceed = false
let token = tokenTextField.text.trim()
let requestURL = "https://myapi.com/authenticate/"
// Make this a synchronous HTTP POST request so that we only decide whether
// to proceed with the segue or not once we know if the request was successful
manager.POST(requestURL,
parameters: [ "code" : token ],
success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
proceed = true
NSLog("Success! Response is (responseObject.description)")
},
failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
println("Failure! Error is: (error.localizedDescription)")
proceed = false
self.displayLoginAttempErrorAlert()
}).waitUntilFinished()
println("what a hard thing")
return proceed
但是,这段代码在success
或error
回调中打印任何内容之前打印"what a hard thing"
,所以它显然是异步的。由于上面解释的原因,我希望它是同步的。我怎样才能强迫这种行为?
请记住,请求本身没有错。我只是想确保事情的正确顺序。
UPDATE:我知道强制同步可能会阻塞UI,这对我来说很好。这就像一个登录屏幕,在发出请求和到达响应之间不应该发生任何事情。
提前感谢
您可以:
- 将
manager
的completionQueue
指定为主队列之外的其他内容(这样在阻塞主线程、等待调用完成处理程序时就不会死锁) dispatch_semaphore_semaphore
- CCD_ 11请求的完成块内的信号量;以及
dispatch_semaphore_wait
用于请求之后但从函数返回之前的信号量
但在我看来,让异步方法同步运行从根本上来说是不正确的方法。这不仅是一个糟糕的用户体验,限制了你的用户界面等,而且你还面临着被监管程序杀死你的应用程序的风险。
与其让异步进程在shouldPerformSegueWithIdentifier
中同步运行,不如使用一种标准的异步模式:
- 将您可能拥有的现有片段从UIKit控件中移除到下一个场景
- 在视图控制器之间创建一个新的segue(如图所示),该segue不会自动执行,而只能通过编程执行(见下文)
- 具有执行异步请求的
IBAction
,并且具有完成块 - 根据需要以编程方式启动segue
为什么不在成功块中调用viewController
。。。我们也有同样的情况,用户有一个登录屏幕,在进行身份验证时,如果失败,则我们需要在成功时显示警报,否则将其重定向到homeViewController
。
如果您使用queueCompletion
块,它将与在队列中只执行一个操作的成功块中处理它相同。
仍然需要同步调用,然后使用iOS 的NSURLConnection类
-[NSURLConnection sendSynchronousRequest:returningResponse:error]