执行 segue 时的异步检查
Posted
技术标签:
【中文标题】执行 segue 时的异步检查【英文标题】:Async checking when perform segue 【发布时间】:2018-10-04 07:41:06 【问题描述】:我的应用有两个 ViewController,LoginViewController,MainViewController
在故事板中,我创建了一个从 LoginViewController 到 MainViewController 的 segue
现在我用Moya实现登录功能,但我想保持segue
所以我在 LoginViewController 中写了这个函数
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool
var ret = false
let provider = MoyaProvider<MyApi>()
provider.request(.login(username : inUsername.text! , password : inPassword.text! )) result in
switch result
case let .success(moyaResponse):
let data = moyaResponse.data
do
let decoder = JSONDecoder()
let user = try decoder.decode(Login.self, from: data)
if(user.status == 1)
ret = true
else
print(user.msg)
catch
print("error")
case let .failure(error):
ret = false
return ret
但是moya请求是异步的,这个函数会在响应之前返回,所以这个函数永远不会返回true
如何做到这一点?
更新:
现在我将请求移到按钮 IBAction,但它仍然不起作用
如果我删除shouldPerformSegue
,它仍然会在回调之前转到下一个视图控制器
如果我在shouldPerformSegue
中返回true,即使登录失败也会转到下一个视图控制器
如果我在shouldPerformSegue
中返回false,即使登录成功也不会进入下一个viewcontroller
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool
return true // always to next
return false // never to next
@IBAction func clickLogin(_ sender: Any)
let provider = MoyaProvider<ZfuApi>()
provider.request(.login(username : inUsername.text! , password : inPassword.text! )) result in
switch result
case let .success(moyaResponse):
let data = moyaResponse.data
do
let decoder = JSONDecoder()
let user = try decoder.decode(Login.self, from: data)
if(user.status == 1)
self.performSegue(withIdentifier: "loginToMain", sender: sender)
else
print(user.msg)
catch
print("error")
case let .failure(error):
print(error.response?.description)
【问题讨论】:
将此请求移至某个登录按钮处理程序。一旦你得到状态然后执行segue
。
在登录按钮IBAction
中执行异步请求。当请求回调并登录成功时,调用self.performSegue(withIdentifier:sender:)
我添加了一个基于当前实现的答案。可以试试吗?
【参考方案1】:
您不能在 shouldPerformSegue 中使用 async 方法,但您可以在执行 segue 之前执行 async 方法,然后在完成块中调用 performSegue(withIdentifier:sender:)
。
【讨论】:
这行不通,现在我将请求移至 IBAction ,但我应该在shouldPerformSegue
中返回什么?如果我返回 ture,它总是进入下一个视图,如果我返回 false,它永远不会进入下一个视图
@Ilya-Kharabet 的建议是正确的。 shouldPerformSegue
最好用于停止已在情节提要文件中以编程方式定义的 segue,否则它们将始终执行,正如您所注意到的。另一种方法是在情节提要中定义 segue,不是从控件到新视图控制器,而是从控制器到控制器,然后只能在代码中激活。然后,在您的异步代码中,执行您在shouldPerformSegue()
中的检查。如果通过,您可以通过使用performSegue()
调用segue 来手动执行segue。
现在好了,我只是去掉按钮segue,然后从控制器创建一个新的segue,然后一切正常。【参考方案2】:
您可以引入一个属性来执行segue
,如下所示,
var isLoggedIn: Bool = false
didSet
self.performSegue(withIdentifier: "loginToMain", sender: self)
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool
return isLoggedIn
@IBAction func clickLogin(_ sender: Any)
let provider = MoyaProvider<ZfuApi>()
provider.request(.login(username : inUsername.text! , password : inPassword.text! )) result in
switch result
case let .success(moyaResponse):
let data = moyaResponse.data
do
let decoder = JSONDecoder()
let user = try decoder.decode(Login.self, from: data)
if(user.status == 1)
self.isLoggedIn = true
else
print(user.msg)
catch
print("error")
case let .failure(error):
print(error.response?.description)
【讨论】:
是的,我试过了,这个没问题,但最后我用controller to controller segue,因为这样更好。 没错,这是更好的方法。以上是关于执行 segue 时的异步检查的主要内容,如果未能解决你的问题,请参考以下文章
iOS8 UITableView 和 Cell - 自动布局高度 - 触摸和执行 segue 时的移位/垂直偏移错误