巧妙化解dismissViewController闪烁问题
问题描述
最近项目里面涉及到一个解锁的界面,这个提示解锁界面在 present
一个人脸解锁的 ViewController
,人脸解锁完成后会有一个 delegate
回调人脸验证结果,并且人脸验证界面自动 dismiss
掉。
如果解锁成功的话,逻辑上人脸验证界面一 dismiss
掉就应该显示 app 的主界面,相对于提示解锁界面在人脸验证 dismiss
同时应该消失。而人脸验证失败的话,提示解锁界面就应该继续覆盖在主界面上,给用户更多提示并引导进一步的操作。
这里面就涉及到 ViewController
生命周期的问题,由提示解锁界面 present
的人脸验证界面没有完全 dismiss
之前是没办法 dismiss 掉解锁界面的,否则就可能出现空指针等问题。
同时使用的SDK并没有回调 viewWillDisappear
事件,所以 delegate
回调跟 viewWillDisappear
的关系与顺序是不可预测的。如果在 delegate
回调中执行 dismiss
,那么在人脸验证界面消失的时候就会看到提示解锁界面闪了一下。
本来打算使用 UIView
来解决这个问题,但是因为 UIView
没有办法接受 delegate
回调,就会引入更多奇怪的问题。最后终于想到了一个不算特别优雅,但是很巧妙的方式解决这个问题。分享之,希望对你有帮助。
解决思路
既然不能直接 dismiss
,那么是否可以将这个 ViewController
透明呢,也就是在人脸验证界面 present
完成后,将提示解锁界面变成透明的,然后如果回调结果不是,马上设置提示解锁界面为原来的值。
经过查找资料和做了简单的原型验证后,发行这个方法可行,也很简单,下面以 Swift
代码简单进行演示
解决方法
首先在显示解锁提示页面设置相关的属性,这里以 Segue
实现为例。
主要设置两个参数:
modalPresentationStyle
设置为OverCurrentContext
.modalTransitionStyle
设置为CrossDissolve
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "ShowLockVC") {
let lockedVC : LockedViewController = segue.destinationViewController as! LockedViewController
lockedVC.modalPresentationStyle = .OverCurrentContext
lockedVC.modalTransitionStyle = .CrossDissolve
}
}
接下来当人脸验证界面 present
完成后将当前界面(解锁提示)的 alpha
设置为 0,让界面透明:
self.presentViewController(faceVerifyView as! UIViewController, animated: true, completion: { () -> Void in
self.view.alpha = 0
})
最后就是处理人脸验证回调结果,如果成功则 dismiss
解锁提示界面(人脸验证界面会自动 dismiss
):
func superID(sender: SuperID!, faceVerifyResponse state: SIDFACEVerifyState) {
if (state == SIDFACEVerifyState.SIDFaceVerifySucceed) {
self.dismissViewControllerAnimated(false, completion: nil)
} else {
self.view.alpha = 1
}
}
问题就这样解决了。
参考
原文链接:https://blog.yourtion.com/solve-dismissviewcontroller-blink.html