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。它看起来像这样:
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:
注意事项:
- The
LabelViewController
and theButtonViewController
know nothing about theViewController
that uses them. This makes it easier to reuse them. You could embed them in another viewController and as long as you properly implement theStringTaker
protocol and set up thedelegate
, everything works. - 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 theViewController
.
LabelViewController和ButtonViewController对使用它们的ViewController一无所知。这样可以更轻松地重用它们。您可以将它们嵌入到另一个viewController中,只要您正确实现StringTaker协议并设置委托,一切正常。
在命名嵌入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:
注意事项:
- The
LabelViewController
and theButtonViewController
know nothing about theViewController
that uses them. This makes it easier to reuse them. You could embed them in another viewController and as long as you properly implement theStringTaker
protocol and set up thedelegate
, everything works. - 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 theViewController
.
LabelViewController和ButtonViewController对使用它们的ViewController一无所知。这样可以更轻松地重用它们。您可以将它们嵌入到另一个viewController中,只要您正确实现StringTaker协议并设置委托,一切正常。
在命名嵌入segues中然后在prepareForSegue中正确设置委托的关键。将Container添加到ViewController后,可以在Document Outline视图中找到segue。