强制 AFNetwork POST 请求同步
Force AFNetwork POST request to be synchronous
我有一个按钮,通过 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
开始请求之前;
dispatch_semaphore_signal
请求完成块内的信号量;和
dispatch_semaphore_wait
用于请求之后的信号量,但在您 return 从您的函数之前。
但在我看来,让异步方法同步运行从根本上说是不正确的方法。它不仅是一个糟糕的用户体验,限制了你的 UI 等,而且你还有被看门狗进程杀死你的应用程序的风险。
与其让异步进程在 shouldPerformSegueWithIdentifier
中同步运行,不如采用标准的异步模式:
- 从 UIKit 控件中删除您可能拥有的现有 segue 到下一个场景;
- 在视图控制器之间创建一个新的 segue(如 shown here),它不会自动执行,而只能以编程方式执行(见下文);
- 有一个执行异步请求的
IBAction
,并且有一个 的完成块
- 根据需要以编程方式启动 segue。
你为什么不在成功块中调用你的 viewController
...我们也有同样的情况,用户有一个登录屏幕,如果发生身份验证失败,那么我们需要显示警报,否则在成功时重定向它至 homeViewController
。
如果您使用 queueCompletion
块,如果您只在队列中执行一个操作,它将与在成功块中处理它相同。
仍然需要同步调用然后使用 iOS
的 NSURLConnection class
-[NSURLConnection sendSynchronousRequest:returningResponse:error]
我有一个按钮,通过 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
开始请求之前;dispatch_semaphore_signal
请求完成块内的信号量;和dispatch_semaphore_wait
用于请求之后的信号量,但在您 return 从您的函数之前。
但在我看来,让异步方法同步运行从根本上说是不正确的方法。它不仅是一个糟糕的用户体验,限制了你的 UI 等,而且你还有被看门狗进程杀死你的应用程序的风险。
与其让异步进程在 shouldPerformSegueWithIdentifier
中同步运行,不如采用标准的异步模式:
- 从 UIKit 控件中删除您可能拥有的现有 segue 到下一个场景;
- 在视图控制器之间创建一个新的 segue(如 shown here),它不会自动执行,而只能以编程方式执行(见下文);
- 有一个执行异步请求的
IBAction
,并且有一个 的完成块
- 根据需要以编程方式启动 segue。
你为什么不在成功块中调用你的 viewController
...我们也有同样的情况,用户有一个登录屏幕,如果发生身份验证失败,那么我们需要显示警报,否则在成功时重定向它至 homeViewController
。
如果您使用 queueCompletion
块,如果您只在队列中执行一个操作,它将与在成功块中处理它相同。
仍然需要同步调用然后使用 iOS
的 NSURLConnection class-[NSURLConnection sendSynchronousRequest:returningResponse:error]