如何将数据从一个容器传递到另一个容器,这两个容器都嵌入在swift中的同一个uiviewcontroller中?

时间:2022-09-24 19:05:22

I have a parent UIViewController and it has two different view containers - each of them has embedded UIViewController inside. It looks somehow like this:

我有一个父UIViewController,它有两个不同的视图容器 - 每个容器内部都嵌入了UIViewController。它看起来像这样:

如何将数据从一个容器传递到另一个容器,这两个容器都嵌入在swift中的同一个uiviewcontroller中?

I want to change the label on the right container when user presses the button stored on the left one.

当用户按下左侧存储的按钮时,我想更改右侧容器上的标签。

So far I was able to do it while having a button placed in a parent view controller, then I was just using a protocol:

到目前为止,我能够在父视图控制器中放置按钮的同时执行此操作,然后我只使用协议:

  • in my parent component I had:

    在我的父组件中我有:

    class ParentController: UIViewController {
    
        var delegateEmbedded:HandleEmbedded?
    
        override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "segueToFirstEmbeddedController"){
    
            if let embeddedView = segue.destinationViewController as? EmbeddedContainer {
    
               self.delegateEmbedded = embeddedView
             } 
    
    
         }
    
  • in my container-embedded UIViewController I had:

    在我的容器嵌入式UIViewController中我有:

    protocol HandleEmbedded: class {
        func setName(label: String)
    }
    
    class EmbeddedContainer: UITableViewController, HandleYourChat{
    
        func setName(label: String){
            print("setting label to \(label)")
        }
    }
    

Situation above works when I have the button placed in a parent controller and want to change the label inside a container. But what happens and how should I pass the data when the button is also embedded, but in a different container than the label? Do I have to pass the data through the parent controller? What's the best way for doing so?

当我将按钮放在父控制器中并想要更改容器内的标签时,上面的情况有效。但是当嵌入按钮时,我应该如何传递数据,但是在与标签不同的容器中?我是否必须通过父控制器传递数据?这样做的最佳方法是什么?

1 个解决方案

#1


1  

To pass data from one embedded ViewController to another embedded ViewController, have the parent handle the transfer. Here I have provided a complete example with three ViewControllers and a single StringTaker protocol. Both the main ViewController and the LabelViewController implement this protocol. The main ViewController takes a string from the ButtonViewController and passes it on to the embedded LabelViewController.

要将数据从一个嵌入的ViewController传递到另一个嵌入的ViewController,请让父处理传输。在这里,我提供了一个包含三个ViewControllers和一个StringTaker协议的完整示例。主ViewController和LabelViewController都实现了这个协议。主ViewController从ButtonViewController获取一个字符串并将其传递给嵌入的LabelViewController。

ViewController.swift

import UIKit

protocol StringTaker: class {
    func takeString(string: String)
}

class ViewController: UIViewController, StringTaker {

    weak var stringTaker: StringTaker?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "EmbedButtonViewController" {
            let dvc = segue.destinationViewController as! ButtonViewController
            dvc.delegate = self
        } else if segue.identifier == "EmbedLabelViewController" {
            let dvc = segue.destinationViewController as! LabelViewController
            stringTaker = dvc
        }
    }

    // Receive the string from the ButtonViewController
    func takeString(string: String) {
        // Pass it to the LabelViewController
        stringTaker?.takeString(string)
    }
}

ButtonViewController.swift

import UIKit

class ButtonViewController: UIViewController {

    weak var delegate: StringTaker?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func generateString(sender: UIButton) {
        let cities = ["Boston", "Paris", "Sydney", "Mumbai", "Lima"]

        // Pick a random city
        let city = cities[Int(arc4random_uniform(UInt32(cities.count)))]

        // Pass the string to the delegate
        delegate?.takeString(city)
    }
}

LabelViewController.swift

import UIKit

class LabelViewController: UIViewController, StringTaker {

    @IBOutlet weak var myLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func takeString(string: String) {
        myLabel.text = string
    }
}

Things to note:

注意事项:

  1. The LabelViewController and the ButtonViewController know nothing about the ViewController that uses them. This makes it easier to reuse them. You could embed them in another viewController and as long as you properly implement the StringTaker protocol and set up the delegate, everything works.
  2. LabelViewController和ButtonViewController对使用它们的ViewController一无所知。这样可以更轻松地重用它们。您可以将它们嵌入到另一个viewController中,只要您正确实现StringTaker协议并设置委托,一切正常。

  3. The key to hooking this up in in naming the embed segues and then properly setting up the delegates in prepareForSegue. The segues can be found in the Document Outline view once the Container is added to the ViewController.
  4. 在命名嵌入segues中然后在prepareForSegue中正确设置委托的关键。将Container添加到ViewController后,可以在Document Outline视图中找到segue。

#1


1  

To pass data from one embedded ViewController to another embedded ViewController, have the parent handle the transfer. Here I have provided a complete example with three ViewControllers and a single StringTaker protocol. Both the main ViewController and the LabelViewController implement this protocol. The main ViewController takes a string from the ButtonViewController and passes it on to the embedded LabelViewController.

要将数据从一个嵌入的ViewController传递到另一个嵌入的ViewController,请让父处理传输。在这里,我提供了一个包含三个ViewControllers和一个StringTaker协议的完整示例。主ViewController和LabelViewController都实现了这个协议。主ViewController从ButtonViewController获取一个字符串并将其传递给嵌入的LabelViewController。

ViewController.swift

import UIKit

protocol StringTaker: class {
    func takeString(string: String)
}

class ViewController: UIViewController, StringTaker {

    weak var stringTaker: StringTaker?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "EmbedButtonViewController" {
            let dvc = segue.destinationViewController as! ButtonViewController
            dvc.delegate = self
        } else if segue.identifier == "EmbedLabelViewController" {
            let dvc = segue.destinationViewController as! LabelViewController
            stringTaker = dvc
        }
    }

    // Receive the string from the ButtonViewController
    func takeString(string: String) {
        // Pass it to the LabelViewController
        stringTaker?.takeString(string)
    }
}

ButtonViewController.swift

import UIKit

class ButtonViewController: UIViewController {

    weak var delegate: StringTaker?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func generateString(sender: UIButton) {
        let cities = ["Boston", "Paris", "Sydney", "Mumbai", "Lima"]

        // Pick a random city
        let city = cities[Int(arc4random_uniform(UInt32(cities.count)))]

        // Pass the string to the delegate
        delegate?.takeString(city)
    }
}

LabelViewController.swift

import UIKit

class LabelViewController: UIViewController, StringTaker {

    @IBOutlet weak var myLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func takeString(string: String) {
        myLabel.text = string
    }
}

Things to note:

注意事项:

  1. The LabelViewController and the ButtonViewController know nothing about the ViewController that uses them. This makes it easier to reuse them. You could embed them in another viewController and as long as you properly implement the StringTaker protocol and set up the delegate, everything works.
  2. LabelViewController和ButtonViewController对使用它们的ViewController一无所知。这样可以更轻松地重用它们。您可以将它们嵌入到另一个viewController中,只要您正确实现StringTaker协议并设置委托,一切正常。

  3. The key to hooking this up in in naming the embed segues and then properly setting up the delegates in prepareForSegue. The segues can be found in the Document Outline view once the Container is added to the ViewController.
  4. 在命名嵌入segues中然后在prepareForSegue中正确设置委托的关键。将Container添加到ViewController后,可以在Document Outline视图中找到segue。