是否可以在情节提要中定义“通用”展开转场?

Posted

技术标签:

【中文标题】是否可以在情节提要中定义“通用”展开转场?【英文标题】: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?

【问题讨论】:

【参考方案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。

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

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

    李>

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

    因为你在初始 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 会发生什么?

以上是关于是否可以在情节提要中定义“通用”展开转场?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 在没有情节提要的情况下展开 segue

在 Interface Builder 中定义“通用”segue

如何使用情节提要从自定义 uitableviewcell 正确启动弹出框转场

如何以编程方式创建展开转场[重复]

如何使用情节提要从 UIBarButtonItem 触发转场?

IOS-如何在情节提要上为通用设备的 UIscrollview 设置框架?