有很多方法可以做到这一点,比如简单地将视图控制器作为属性传递给新实例。但在您的情况下,创建一个静态变量可能更有意义,该变量以与导航控制器相同的方式保存视图控制器的堆栈。
如果您只在UIViewController 子类之间执行此操作,我建议您创建它的另一个子类,所有其他视图控制器都继承该子类。让我们称之为TrackedViewController。
class TrackedViewController : UIViewController {
static var currentViewController: TrackedViewController?
static var previousViewController: TrackedViewController?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
TrackedViewController.previousViewController = TrackedViewController.currentViewController
TrackedViewController.currentViewController = self
}
}
现在您需要更改所有要跟踪的视图控制器,以便它们都从TrackedViewController 继承为class MyViewController : TrackedViewController {。差不多就是这样。现在,在项目中的任何位置,您都可以通过TrackedViewController.currentViewController 找到您当前的视图控制器,并通过TrackedViewController.previousViewController 找到之前的视图控制器。所以你可以这样说:
if let myController = TrackedViewController.previousViewController as? MyViewController {
// Code here if the screen was reached from MyViewController instance
}
现在我这样做的方式是通过视图控制器的实例,这可能会产生一些副作用。
- 您可能遇到的最大问题是前一个控制器与当前视图控制器一起被保留。这意味着您的内存中可能有 2 个不需要的控制器。
- 如果你从控制器
A 到B 到C 再回到B,那么之前的视图控制器是C,而不是A。这可能是预期的结果,也可能不是。
- 系统将忽略所有其他视图控制器。因此,如果您使用的不是
TrackedViewController 的子类,则调用将被忽略:A 到B 到UITableViewController 到C 将报告C 由B 提供,即使中间还有另一个屏幕。同样,这可能是预期的结果。
所以如果第 2 点和第 3 点对您有好处,那么您应该只决定天气来修复第 1 点。您可以使用weak 删除两个属性的保留,但您会丢失之前视图的信息如果控制器被释放,控制器。所以另一种选择是使用一些标识符:
class TrackedViewController : UIViewController {
static var currentViewControllerID: String?
static var previousViewControllerID: String?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
TrackedViewController.previousViewControllerID = TrackedViewController.currentViewControllerID
TrackedViewController.currentViewControllerID = self.screenIdentifier
}
var screenIdentifier: String {
return "Default Screen" // TODO: every view controller must override this method and have unique identifier
}
}
你也可以用一些枚举或其他东西替换字符串。将它们与一些相关的值结合起来可以创建一个非常强大的工具。