滑动到 popViewController 在 iOS 13 中不工作
Swipe to popViewController not working in iOS 13
在下面的代码中,我已经完成了滑动到 popViewController 的操作。这适用于 ios 12 或更旧版本,但当它在 iOS 13 中为 运行 时,它不起作用。 Xcode 的当前版本是 11.1
此外,我正在使用本机 NavigationController 和导航栏。所以我认为这不是导航控制器的问题。
import UIKit
class SwipeNavigationController: UINavigationController {
// MARK: - Lifecycle
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
delegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
// This needs to be in here, not in init
interactivePopGestureRecognizer?.delegate = self
}
deinit {
delegate = nil
interactivePopGestureRecognizer?.delegate = nil
}
// MARK: - Overrides
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
duringPushAnimation = true
super.pushViewController(viewController, animated: animated)
}
// MARK: - Private Properties
fileprivate var duringPushAnimation = false
}
// MARK: - UINavigationControllerDelegate
extension SwipeNavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }
swipeNavigationController.duringPushAnimation = false
}
}
// MARK: - UIGestureRecognizerDelegate
extension SwipeNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard gestureRecognizer == interactivePopGestureRecognizer else {
return true // default value
}
// Disable pop gesture in two situations:
// 1) when the pop animation is in progress
// 2) when user swipes quickly a couple of times and animations don't have time to be performed
if (self.visibleViewController?.isKind(of: CheckOTPViewController.self))! {
return false
}
if (self.visibleViewController?.isKind(of: ForgotPasswordViewController.self))! {
return false
}
return viewControllers.count > 1 && duringPushAnimation == false
}
}
您可以尝试使用以下检查 iOS 13 的条件来检查弹出视图控制器:
if #available(iOS 13.0, *) {
self.navigationController?.popToViewController(vc as! YourVC, animated: true)
} else {
// Fallback on earlier versions
}
您必须查看 iOS 13 的 UINavigationController 更改:
https://medium.com/@hacknicity/view-controller-presentation-changes-in-ios-13-ac8c901ebc4e
经过多次尝试,我终于解决了这个问题。
问题是调用 deinit 方法而不是在 viewDidLoad 方法上设置正确的委托。
下面是工作代码。
import UIKit
class SwipeNavigationController: UINavigationController {
// MARK: - Lifecycle
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
delegate = self
interactivePopGestureRecognizer?.delegate = self
navigationItem.backBarButtonItem?.isEnabled = true
interactivePopGestureRecognizer?.isEnabled = true
}
override func viewDidLoad() {
super.viewDidLoad()
// This needs to be in here, not in init
setup()
}
// MARK: - Overrides
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
duringPushAnimation = true
super.pushViewController(viewController, animated: animated)
}
// MARK: - Private Properties
fileprivate var duringPushAnimation = false
}
// MARK: - UINavigationControllerDelegate
extension SwipeNavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }
swipeNavigationController.duringPushAnimation = false
}
}
// MARK: - UIGestureRecognizerDelegate
extension SwipeNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard gestureRecognizer == interactivePopGestureRecognizer else {
return true // default value
}
// Disable pop gesture in two situations:
// 1) when the pop animation is in progress
// 2) when user swipes quickly a couple of times and animations don't have time to be performed
if (self.visibleViewController?.isKind(of: CheckOTPViewController.self))! {
return false
}
if (self.visibleViewController?.isKind(of: ForgotPasswordViewController.self))! {
return false
}
return viewControllers.count > 1 && duringPushAnimation == false
}
}
在下面的代码中,我已经完成了滑动到 popViewController 的操作。这适用于 ios 12 或更旧版本,但当它在 iOS 13 中为 运行 时,它不起作用。 Xcode 的当前版本是 11.1
此外,我正在使用本机 NavigationController 和导航栏。所以我认为这不是导航控制器的问题。
import UIKit
class SwipeNavigationController: UINavigationController {
// MARK: - Lifecycle
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
delegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
// This needs to be in here, not in init
interactivePopGestureRecognizer?.delegate = self
}
deinit {
delegate = nil
interactivePopGestureRecognizer?.delegate = nil
}
// MARK: - Overrides
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
duringPushAnimation = true
super.pushViewController(viewController, animated: animated)
}
// MARK: - Private Properties
fileprivate var duringPushAnimation = false
}
// MARK: - UINavigationControllerDelegate
extension SwipeNavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }
swipeNavigationController.duringPushAnimation = false
}
}
// MARK: - UIGestureRecognizerDelegate
extension SwipeNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard gestureRecognizer == interactivePopGestureRecognizer else {
return true // default value
}
// Disable pop gesture in two situations:
// 1) when the pop animation is in progress
// 2) when user swipes quickly a couple of times and animations don't have time to be performed
if (self.visibleViewController?.isKind(of: CheckOTPViewController.self))! {
return false
}
if (self.visibleViewController?.isKind(of: ForgotPasswordViewController.self))! {
return false
}
return viewControllers.count > 1 && duringPushAnimation == false
}
}
您可以尝试使用以下检查 iOS 13 的条件来检查弹出视图控制器:
if #available(iOS 13.0, *) {
self.navigationController?.popToViewController(vc as! YourVC, animated: true)
} else {
// Fallback on earlier versions
}
您必须查看 iOS 13 的 UINavigationController 更改:
https://medium.com/@hacknicity/view-controller-presentation-changes-in-ios-13-ac8c901ebc4e
经过多次尝试,我终于解决了这个问题。 问题是调用 deinit 方法而不是在 viewDidLoad 方法上设置正确的委托。
下面是工作代码。
import UIKit
class SwipeNavigationController: UINavigationController {
// MARK: - Lifecycle
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
delegate = self
interactivePopGestureRecognizer?.delegate = self
navigationItem.backBarButtonItem?.isEnabled = true
interactivePopGestureRecognizer?.isEnabled = true
}
override func viewDidLoad() {
super.viewDidLoad()
// This needs to be in here, not in init
setup()
}
// MARK: - Overrides
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
duringPushAnimation = true
super.pushViewController(viewController, animated: animated)
}
// MARK: - Private Properties
fileprivate var duringPushAnimation = false
}
// MARK: - UINavigationControllerDelegate
extension SwipeNavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }
swipeNavigationController.duringPushAnimation = false
}
}
// MARK: - UIGestureRecognizerDelegate
extension SwipeNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard gestureRecognizer == interactivePopGestureRecognizer else {
return true // default value
}
// Disable pop gesture in two situations:
// 1) when the pop animation is in progress
// 2) when user swipes quickly a couple of times and animations don't have time to be performed
if (self.visibleViewController?.isKind(of: CheckOTPViewController.self))! {
return false
}
if (self.visibleViewController?.isKind(of: ForgotPasswordViewController.self))! {
return false
}
return viewControllers.count > 1 && duringPushAnimation == false
}
}