在我的应用中,主ViewController每秒从传感器获取数据60次。为了显示数据,我有两个ContainerViews,一个显示原始数据,另一个显示在图形中。
我如何不断地将数据从mainVC发送到ContainerView或让ContiainerViews访问mainVC中的变量?
答案 0 :(得分:1)
有很多方法可以对此进行切片。
我建议您不要在视图控制器中从传感器收集数据。这实际上不是视图控制器的工作。当有多个对象需要该传感器数据时,情况会变得更糟。
可能最干净的设计是创建一个单独的对象(我将其称为SensorManager),该对象收集您的传感器数据并将其传递给任何关心的人。
您可以让SensorManager
使用NotificationCenter
广播通知,然后让所有感兴趣的对象为他们关心的通知添加观察者。这使SensorManager
与获得有关传感器数据通知的对象之间的耦合非常松散。缺点是代码更难调试。
或者,可以将SensorManager
设置为具有要通知的对象数组。我将定义一个协议,该协议具有一个或多个通过传感器数据调用的方法,并使SensorManager维护符合该协议的客户端对象数组。当SensorManager拥有新的传感器数据时,它将循环遍历客户端对象的数组并在每个对象上调用适当的方法以将每个新数据告知每个对象。第二个选项有点类似于委托设计模式,但是是一对多的,委托模式是一对一的信息传递。
如果您不喜欢在主视图控制器中收集传感器数据的想法,并且使用embed segues创建子视图控制器,则可以在主视图控制器中编写一个prepareForSegue()
方法来寻找目的地查看符合协议的控制器。我们称之为SensorDataListener
。主视图控制器可以将这些对象保存在数组中,并使用协议中的方法将新传感器数据通知给这些对象。 (最后一种方法类似于创建SensorManager
对象的方法,但是它将是充当该角色的主视图控制器。)
//At the top of your class:
protocol SensorDataListener {
func newSensorData(_ SensorData)
}
var sensorClients = [SensorDataListener]()
//...
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.desination as SensorDataListener {
sensorClients.append(dest)
}
}
然后当您收到新数据时
sensorClients.forEach { sensorClient in
sensorClient.newSensorData(sensorData)
}
答案 1 :(得分:0)
将两个子视图控制器都作为主视图控制器中的变量,并像这样将它们从self.childViewControllers
中的主视图控制器的viewDidLoad
挂钩。
class ViewController: UIViewController {
var firstViewController: FirstViewController!
var secondViewController: SecondViewController!
override func viewDidLoad() {
super.viewDidLoad()
for vc in self.childViewControllers {
if let firstViewController = vc as? FirstViewController {
self.firstViewController = firstViewController
}
if let secondViewController = vc as? SecondViewController {
self.secondViewController = secondViewController
}
}
}
func sensorDataUpdated(data: Any) {
self.firstViewController.data = data
self.secondViewController.data = data
}
}
这是一个内部视图控制器如何工作的示例,它们的逻辑相同:
class FirstViewController: UIViewController {
var data: Any? {
didSet {
self.updateUI();
}
}
func updateUI() {
guard let data = self.data else { return }
// Perform UI updates
}
}