【问题标题】:Is it possible to define a "generic" unwind segue in the storyboard?是否可以在情节提要中定义“通用”展开转场?
【发布时间】:2018-02-21 10:34:04
【问题描述】:

我是 IOS 开发新手,来自 Android 背景。一旦用户注销,我正在寻找一种返回原始视图控制器的方法。

这篇帖子How can I go back to the initial view controller in Swift? 建议我应该使用展开转场。

但是,因为我的应用程序的用户会话可能随时(以及在任何视图控制器期间)到期。这意味着我需要从每个视图控制器到根视图控制器进行倒带转接!此外,这也会导致一些重复的代码,因为每个视图控制器都需要一种方法来引用自己唯一的 segue ID。

最初,我希望继承 UIViewController 并创建一个 CustomViewController,然后我的所有其他 ProfileViewController, LoginViewController 都将继承它。

CustomViewController 将提供辅助方法,例如func logOut()。有没有办法做到这一点,也许是通过一些通用的 unwind segue?

【问题讨论】:

    标签: ios swift xcode


    【解决方案1】:

    你不能有通用的展开转场。您不能继承 ViewController 的故事板属性,包括与 ViewController 关联的 segue。但是你不需要一个通用的 segue 来解决你的问题。

    您可以拥有一个BaseViewController,而您的所有其他视图控制器都将从BaseViewController 扩展。您可以添加您的逻辑来验证用户是否仍在您的BaseViewController 中登录(我无法为此编写代码,因为我没有看到您的代码库)。

    如果用户不再登录,那么您只需调用

    class BaseViewController : UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            //implement your logic to monitor if user is still logged in if user not logged in simply call
            self.logOut()
        }
    
        func logOut() {
           //each child view controller will override and handle log out condition specifically for that ViewController
        }
    }
    

    最后,要加载初始 ViewController,您可以简单地说 pop all viewController 在它上面。假设您的 initialViewController 是您的应用程序的 rootViewController,您可以简单地将 BaseViewController 中的逻辑修改为

       override func viewDidLoad() {
            super.viewDidLoad()
            //implement your logic to monitor if user is still logged in if user not logged in simply call
            self.logOut()
            UIApplication.shared.keyWindow?.rootViewController?.navigationController?.popToRootViewController(animated: true)
        }
    

    方法的问题:

    根据您的问题描述,我相信您的初始视图控制器保存在 ViewController 堆栈中,您只需在注销时展开到初始 ViewController。

    虽然这种方法有效,但存在三个问题

    1. 初始 ViewController 不必要地保存在内存中,而在用户注销之前它永远不会重新出现,因此您实际上可以在用户登录后将其删除,并在用户注销后将其重新打开。

      李>
    2. 如果用户登录并退出应用程序并重新启动应用程序,应用程序将加载初始视图控制器,但如果用户已经登录,为什么还要再次向他显示初始视图控制器??

    3. 因为你在初始 ViewController 上推送其他 VC,这也意味着用户可以简单地继续点击返回按钮并返回到初始 viewController,这没有意义,因为用户点击返回按钮怎么会有与用户登录状态有什么关系??不是吗??

    那么更好的解决方案是什么?

    在应用启动时更改应用的根视图控制器。

    打开你的 AppDelegate 和

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       //check if user is logged in
    
       guard let window = UIApplication.shared.keyWindow else {
            return
       }
    
       if (userIsLoggedIn) {
          //load view controller that you wanna show after login lets say Home
          let homeVC = //instantiate view controller from story board
          UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
                window.rootViewController = homeVC
            }, completion: { completed in
                // maybe do something here
            })
       }
       else {
           //load initial controller 
          let initialVC = //instantiate view controller from story board
          UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
                window.rootViewController = initialVC
            }, completion: { completed in
                // maybe do something here
            })
       }
    }
    

    最后,如果用户没有登录并且你最终加载了初始VC并且一旦用户登录了你的初始VC,你可以使用我上面写的代码来改变root VC

          let initialVC = //instantiate view controller from story board
          UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
                window.rootViewController = initialVC
            }, completion: { completed in
                // maybe do something here
            })
    

    【讨论】:

    • 只有当根 ViewController 是 NavigaitonController 并且登录控制器与根相同时才有效。
    • @mohammadalijf : 编辑答案更详细:) 请稍候
    • @mohammadalijf : 请看一下
    • 我猜旧的 rootViewController 只是超出范围而死了?
    • @AlanSTACK :是的,它应该,除非你有任何强烈的参考。理想情况下,一旦你设置了一个新的 rootview 控制器,就应该调用旧的 rootview 控制器 deinit n 应该给你最后一次机会来清除所有持有的资源 n 准备新状态。
    【解决方案2】:

    如果您想返回登录视图控制器,您可以从下一个视图设置一次倒带(退出)到该视图。然后使用通知中心从应用程序的任何位置发布通知。 “登录旁边”视图观察通知并执行倒带转场。

    【讨论】:

    • 当前视图会发生什么?假设我有LoginVC -> ProfileVC -> CurrentVC 如果我从ProfileVC to LoginVC 开始倒带,CurrentVC 会发生什么?
    猜你喜欢
    • 2010-11-23
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多