是否可以在情节提要中定义“通用”展开转场?
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
会发生什么?以上是关于是否可以在情节提要中定义“通用”展开转场?的主要内容,如果未能解决你的问题,请参考以下文章
在 Interface Builder 中定义“通用”segue
如何使用情节提要从自定义 uitableviewcell 正确启动弹出框转场