【发布时间】:2016-12-05 16:41:53
【问题描述】:
我想以某种方式异步验证 ABPadLockScreen 中的引脚,因为引脚未保存在设备上。我将 Alamofire 与 PromiseKit 一起用于 http 请求以做出承诺。
我曾尝试使用AwaitKit,但问题是我陷入了僵局。
我也尝试过使用semaphore,但结果是一样的。由于我无法更改 ABPadLock 方法以适应诸如完成处理程序之类的东西,因此我需要一些解决方案,因此它是否阻塞主线程并不重要,只要它可以工作即可。
Alamofire 请求方法:
public func loginAsync(pinCode: String?, apiPath: String?) -> Promise<LoginResult>{
return Promise { fullfil, reject in
let params = [
"Pin": pinCode!
]
Alamofire.request(.POST, "\(baseUrl!)/\(apiPath!)", parameters: params).responseObject{(response: Response<LoginResult, NSError>) in
let serverResponse = response.response
if serverResponse!.statusCode != 200 {
reject(NSError(domain: "http", code: serverResponse!.statusCode, userInfo: nil))
}
if let loginResult = response.result.value {
fullfil(loginResult)
}
}
}
}
ABPadLockScreen pin验证方法:
public func padLockScreenViewController(padLockScreenViewController: ABPadLockScreenViewController!, validatePin pin: String!) -> Bool {
let pinCode = pin!
let defaults = NSUserDefaults.standardUserDefaults()
let serverUrl = defaults.stringForKey(Util.serverUrlKey)
let service = AirpharmService(baseUrl: serverUrl)
service.loginAsync(pinCode, apiPath: "sw/airpharm/login").then { loginResult -> Void in
if loginResult.code == HTTPStatusCode.OK {
AirpharmService.id = loginResult.result!.id
}
}
return false // how do i get the result of above async method here?
}
带信号量:
public func padLockScreenViewController(padLockScreenViewController: ABPadLockScreenViewController!, validatePin pin: String!) -> Bool {
var loginResult: LoginResult?
let defaults = NSUserDefaults.standardUserDefaults()
let baseUrl = defaults.stringForKey(Util.serverUrlKey)
let service = AirpharmService(baseUrl: baseUrl)
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
service.loginAsync(pin, apiPath: "sw/airpharm/login").then { loginResultRaw -> Void in
loginResult = loginResultRaw
dispatch_semaphore_signal(semaphore)//after a suggestion from Josip B.
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return loginResult != nil // rudimentary check for now
}
编辑:
在 Josip B 的建议下,我添加了信号量信号,但它仍然不起作用
AirpharmService 是一个包含名为 id 的静态属性和 Alamofire 请求方法的类。
ABPadLockScreen pin 验证在 ViewController 的主线程上完成
已解决编辑:
感谢大家对我和我的 swift 和 iOS 知识的耐心等待。这里有很多很好的答案,最后我只是选择了,在我看来,最简单的解决方案。我听了Losiowaty-s 的建议;当我从服务器收到响应时,实现了一个微调器并手动关闭了锁定屏幕。我用过SwiftSpinner。最终的解决方案如下所示:
public func padLockScreenViewController(padLockScreenViewController: ABPadLockScreenViewController!, validatePin pin: String!) -> Bool {
let defaults = NSUserDefaults.standardUserDefaults()
let baseUrl = defaults.stringForKey(Util.serverUrlKey)
let service = AirpharmService(baseUrl: baseUrl)
SwiftSpinner.show("Logging in. Please wait...")
service.loginAsync(pin, apiPath: "sw/airpharm/login").then { loginResult -> Void in
if loginResult.code == HTTPStatusCode.OK {
SwiftSpinner.hide()
AirpharmService.id = loginResult.result!.id
self.unlockWasSuccessfulForPadLockScreenViewController(padLockScreenViewController)
} else if loginResult.code == HTTPStatusCode.Unauthorized {
let toast = JLToast.makeText("Invalid pin, please try again", duration: 5)
toast.show()
SwiftSpinner.hide()
} else {
let toast = JLToast.makeText("\(loginResult.code) sent from server. Please try again.", duration: 5)
toast.show()
SwiftSpinner.hide()
}
}.error { error in
let toast = JLToast.makeText("\((error as NSError).code) sent from server. Please try again.", duration: 5)
toast.show()
SwiftSpinner.hide()
}
return false
}
【问题讨论】:
-
您说“ABPadLockScreen pin 验证已在主线程上完成”,那么您不应该在那里等待。重构匹配异步调用的验证功能。
-
此函数
padLockScreenViewController是 abpadlockscreen 协议的一部分,该函数由 abpadlockscreen 自动调用。你打算怎么做?如果我问了一个愚蠢的问题,我真的很抱歉,但我只使用 Swift 几天,所以我仍然不知道它是如何工作的。 -
带信号量的代码不完整,添加dispatch_semaphore_signal(semaphore);在 loginResult = loginResultRaw 之后发出信号量继续。
-
不幸的是结果相同
-
@Nikola.Lukovic 您是否使用断点来验证是否已到达此行:
dispatch_semaphore_signal(semaphore)//after a suggestion from Josip B.
标签: ios swift asynchronous alamofire