我有一个父UIViewController
,它有两个不同的视图容器 - 每个容器都嵌入了UIViewController
。它看起来像这样:
当用户按下左侧存储的按钮时,我想更改右侧容器上的标签。
到目前为止,我可以在父视图控制器中放置一个按钮时执行此操作,然后我只是使用协议:
在我的父组件中我有:
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
}
}
在我的容器嵌入式UIViewController中,我有:
protocol HandleEmbedded: class {
func setName(label: String)
}
class EmbeddedContainer: UITableViewController, HandleYourChat{
func setName(label: String){
print("setting label to \(label)")
}
}
当我将按钮放在父控制器中并想要更改容器内的标签时,上面的情况有效。但是当嵌入按钮时,我应该如何传递数据,但是在与标签不同的容器中? 我是否必须通过父控制器传递数据?这样做的最佳方式是什么?
答案 0 :(得分:1)
要将数据从一个嵌入的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
}
}
注意事项:
LabelViewController
和ButtonViewController
对使用它们的ViewController
一无所知。这样可以更轻松地重用它们。您可以将它们嵌入到另一个viewController中,只要您正确实现StringTaker
协议并设置delegate
,一切正常。prepareForSegue
中正确设置委托时,将其连接起来的关键。将容器添加到ViewController
后,可以在文档大纲视图中找到segues。