我如何不断地将数据从父 ViewController 发送到容器 ViewController

How do I constantly send data from parent ViewController to ContainerViewController

在我的应用中,主要 ViewController 每秒从传感器获取数据 60 次。为了显示数据,我有两个 ContainerView,一个显示原始数据,另一个显示在图表中。

如何不断地将数据从我的 mainVC 发送到 ContainerView 或让 ContiainerViews 访问我的 mainVC 中的变量?

有很多切法。

我建议不要在视图控制器中从传感器收集数据。这不是真正的视图控制器的工作。当有多个对象需要该传感器数据时,情况会变得更糟。

可能最简洁的设计是创建一个单独的对象(我将其称为 SensorManager)来收集您的传感器数据并将其传递给任何关心的人。

您可以让 SensorManager 使用 NotificationCenter 广播通知,然后让所有感兴趣的对象为他们关心的通知添加观察者。这使您在 SensorManager 和收到有关传感器数据通知的对象之间的耦合非常松散。缺点是代码更难调试。

或者,可以将您的 SensorManager 设置为具有它通知的对象数组。我将定义一个协议,该协议具有一个或多个使用传感器数据调用的方法,并让 SensorManager 维护一组符合该协议的客户端对象。当 SensorManager 有新的传感器数据时,它将遍历客户端对象数组并在每个对象上调用适当的方法以告知每个对象有关新数据的信息。第二个选项有点像委托设计模式,但是是一对多的,其中委托模式是一对一的信息传递。

如果您执着于在主视图控制器中收集传感器数据的想法,并且使用嵌入转场创建子视图控制器,那么您可以在主视图控制器中编写一个 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)
}

将您的两个子视图控制器都作为主视图控制器中的变量,并将它们从 viewDidLoad 中主视图控制器的 self.childViewControllers 连接起来,就像这样。

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
    }
}