在 swift 中的 tabController 下的 viewController 之间传递数据,事件序列
passing data between viewControllers under a tabController in swift, event sequence
我有一个 UITabController Main,它有两个 UIViewController,A 和 B。在故事板中。每个控制器都有对应的swiftclass,Main,A,B
Main.swift 是 UITabController 的子class 和 UITabBarControllerDelegate 的委托。在它的 viewDidLoad 中,它设置它的 .delegate = self.
在 Main 的 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) 我捕获了选定的选项卡,并采取措施设置一些我希望传递给选定的数据值viewController的变量Y.
在ViewControllerclassA和B中,变量Y有一个var声明。
在每个 ViewController A 和 B 中,在 viewWillAppear 中,我从这个变量 Y 填充本地自定义视图出口。
它不起作用的原因是事件处理的顺序。
我假设点击tab的时候,会先处理Main的tabBarController函数,然后再处理选中的对应viewController的viewWillAppear。事实并非如此。
显然,首先执行选定的(A 或 B)viewController 的 viewWillAppear,然后触发 Main 的 tabBarController。这当然会导致问题,因为我显示由 Y 填充的网点,然后我填充 Y...
这种让 Main 用一些数据填充 A 或 B 的技术是首选,因为 A 和 B 应该不知道彼此的任何信息。但是 Main 对 A 和 B 都非常了解。我真的不想做 singleton/global 数据传递——我更喜欢干净利落地处理它。
关于如何更正此事件序列的顺序或建议另一种(正确的 MVC)技术有什么建议吗?
我的目标:我想将一些数据传递到所选选项卡下的视图层次结构,并让调用者进行传递。接收器视图层次结构应该不关心它是如何接收数据的。
(我有一个丑陋的解决方法,我会重新触发 viewWillappear,但基本上这会导致愚蠢的流程:A.viewWillAppear --> Main.tabBarController --> 强制另一个 A.viewWillAppear)
非常感谢。
代码(经过简化——这是一个已解决的工作示例)
class MainController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self;
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print ("tabBarController didSelect")
let viewController = viewControllers![self.selectedIndex]
if let vc = viewController as? AViewController {
vc.Y = "some valuable data"
}
else if let vc = viewController as? BViewController {
vc.Y = "some valuable data"
}
}
}
class AViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y: String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
print ("viewWillAppear A")
super.viewWillAppear(animated)
YTextField.text = self.Y
}
}
class BViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y: String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
print ("viewWillAppear B")
super.viewWillAppear(animated)
YTextField.text = self.Y
}
}
您正在使用:
// this is called when the tab's ViewController is selected (*after* the tab item is selected (tapped))
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { ... }
何时使用:
// this is called *when* the tab item is selected (tapped)
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { ... }
这里是对你的例子的修改:
import UIKit
class MainViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self;
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
let n = self.selectedIndex
if let tabControllers = viewControllers {
if let _ = tabControllers[n] as? AViewController {
// *current* VC is AViewController
if let vcB = tabControllers[n + 1] as? BViewController {
vcB.Y = "some valuable data from A"
}
}
else if let _ = tabControllers[n] as? BViewController {
// *current* VC is BViewController
if let vcA = tabControllers[n - 1] as? AViewController {
vcA.Y = "some valuable data from B"
}
}
}
}
}
class AViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}
}
class BViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}
}
您需要进行一些额外的处理/检查以确保您到达所需的选项卡。您可能 想在 didSelect item
上的 MainViewController
内设置一个变量,然后在 didSelect viewController
上的 "target" 视图控制器内设置变量。
我有一个 UITabController Main,它有两个 UIViewController,A 和 B。在故事板中。每个控制器都有对应的swiftclass,Main,A,B
Main.swift 是 UITabController 的子class 和 UITabBarControllerDelegate 的委托。在它的 viewDidLoad 中,它设置它的 .delegate = self.
在 Main 的 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) 我捕获了选定的选项卡,并采取措施设置一些我希望传递给选定的数据值viewController的变量Y.
在ViewControllerclassA和B中,变量Y有一个var声明。
在每个 ViewController A 和 B 中,在 viewWillAppear 中,我从这个变量 Y 填充本地自定义视图出口。
它不起作用的原因是事件处理的顺序。
我假设点击tab的时候,会先处理Main的tabBarController函数,然后再处理选中的对应viewController的viewWillAppear。事实并非如此。
显然,首先执行选定的(A 或 B)viewController 的 viewWillAppear,然后触发 Main 的 tabBarController。这当然会导致问题,因为我显示由 Y 填充的网点,然后我填充 Y...
这种让 Main 用一些数据填充 A 或 B 的技术是首选,因为 A 和 B 应该不知道彼此的任何信息。但是 Main 对 A 和 B 都非常了解。我真的不想做 singleton/global 数据传递——我更喜欢干净利落地处理它。
关于如何更正此事件序列的顺序或建议另一种(正确的 MVC)技术有什么建议吗?
我的目标:我想将一些数据传递到所选选项卡下的视图层次结构,并让调用者进行传递。接收器视图层次结构应该不关心它是如何接收数据的。
(我有一个丑陋的解决方法,我会重新触发 viewWillappear,但基本上这会导致愚蠢的流程:A.viewWillAppear --> Main.tabBarController --> 强制另一个 A.viewWillAppear)
非常感谢。
代码(经过简化——这是一个已解决的工作示例)
class MainController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self;
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print ("tabBarController didSelect")
let viewController = viewControllers![self.selectedIndex]
if let vc = viewController as? AViewController {
vc.Y = "some valuable data"
}
else if let vc = viewController as? BViewController {
vc.Y = "some valuable data"
}
}
}
class AViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y: String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
print ("viewWillAppear A")
super.viewWillAppear(animated)
YTextField.text = self.Y
}
}
class BViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y: String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
print ("viewWillAppear B")
super.viewWillAppear(animated)
YTextField.text = self.Y
}
}
您正在使用:
// this is called when the tab's ViewController is selected (*after* the tab item is selected (tapped))
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { ... }
何时使用:
// this is called *when* the tab item is selected (tapped)
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { ... }
这里是对你的例子的修改:
import UIKit
class MainViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self;
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
let n = self.selectedIndex
if let tabControllers = viewControllers {
if let _ = tabControllers[n] as? AViewController {
// *current* VC is AViewController
if let vcB = tabControllers[n + 1] as? BViewController {
vcB.Y = "some valuable data from A"
}
}
else if let _ = tabControllers[n] as? BViewController {
// *current* VC is BViewController
if let vcA = tabControllers[n - 1] as? AViewController {
vcA.Y = "some valuable data from B"
}
}
}
}
}
class AViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}
}
class BViewController: UIViewController {
@IBOutlet weak var YTextField: UITextField!
var Y:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}
}
您需要进行一些额外的处理/检查以确保您到达所需的选项卡。您可能 想在 didSelect item
上的 MainViewController
内设置一个变量,然后在 didSelect viewController
上的 "target" 视图控制器内设置变量。