我尝试通过委托在Container Views
中Swift
之间发送信息,并且当我继续解包错误时执行协议功能。
topContainerViewController.swift
import UIKit
protocol topContainerDelegate{
func send(text:String)
}
class topContainerViewController: UIViewController {
var delegate: topContainerDelegate! = nil
@IBOutlet var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func sendMessage(sender: AnyObject) {
delegate!.send(textField.text!)
}
}
bottomContainerViewController.swift
import UIKit
class bottomContainerViewController: UIViewController, topContainerDelegate {
@IBOutlet var messageLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func send(text: String) {
messageLabel.text = text
}
}
如何在两个容器视图之间正确设置委派?
答案 0 :(得分:2)
您的代码存在问题:
self
。BottomContainerViewController
TopContainerViewController
中,您将代理人的初始值设置为nil,只需将其保留为可选项,然后使用防护装置将其打开。这适用于我的测试应用程序:
protocol TopContainerDelegate : class {
func send(text:String)
}
class TopContainerViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
weak var delegate : TopContainerDelegate?
@IBAction func sendMessage(sender: UIButton) {
guard let delegate = delegate else {
return
}
delegate.send(textField.text!)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
class BottomContainerViewController: UIViewController, TopContainerDelegate {
@IBOutlet weak var messageLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let app = UIApplication.sharedApplication().delegate! as! AppDelegate
if let viewControllers = app.window?.rootViewController?.childViewControllers {
viewControllers.forEach { vc in
if let cont = vc as? TopContainerViewController {
cont.delegate = self
}
}
}
}
func send(text:String) {
messageLabel.text = text
}
}
如果您有任何其他问题,请随时下载我的工作项目并亲自测试。
答案 1 :(得分:2)
我假设你在View A中有两个容器视图,所以请看看:
一种更容易(也更方便?)的方式是A将在您的Container View B& D之间进行通信。 C.这样,您就不必通过整个应用程序来设置代理,如果您的应用程序非常大,也应该有更好的性能。
查看A:
@objc
protocol InformContainerDelegate{
optional func notifyB()
optional func notifyC()
}
var bDelegate: InformContainerDelegate
var cDelegate: InformContainerDelegate
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toContainerB"{
let controller = segue.destinationViewController as! ContainerBViewController
controller.delegate = self // A receives notifications from B
self.bDelegate = controller // sending information from A to B
} else if segue.identifier == "toContainerC"{
let controller = segue.destinationViewController as! ContainerCViewController
controller.delegate = self // A receives notifications from C
self.cDelegate = controller // sending information from A to C
}
}
A现在是B& S的代表。 C和逆。
我们假设您希望B告知C有关某事的内容:
查看B:
protocol BChangedSomethingDelegate{
func informC()
}
class B : UIViewController // or whatever {
//... usual methods
func BDidSomething(){ delegate?.informC!() }
}
现在你需要使A符合B" BChangedSomethingDelegate"的协议:
extension A: BChangedSomethingDelegate {
func informC!(){
cDelegate!.notifyC!()
}
}
对于C,您还必须实现一个协议,然后A将符合它。致力于解决方案并且它的工作非常好。
额外提示:设置断点以测试A,B和C是否是相应的代表,在断点期间按" po xxx"直接在日志中,应用程序被断点停止以检查xxx是什么。
示例:(po cDelegate) - >无或代表
答案 2 :(得分:0)
但是你在topContainerViewController的实例中指定了委托的地方是bottomContainerViewController的实例???
你错过了一个步骤:你还没有分配对象来委托topContainerViewController实例的对象SO YOU GOT ERROR 这意味着你没有指定谁响应委托函数调用的任何调用宾语????如果你没有给谁回应它,那么很明显你会得到错误。 既然,我没有发现你已经创建了topContainerViewController的实例,我猜你是通过使用segue做的。
当您创建topContainerViewController的实例时,您需要指定委托变量。 如果你转到topContainerViewController on button on bottomContainerViewController然后获取bottomContainerViewController的实例并将self指定给委托:
如果你通过segue:给segue提供标识符,我现在给了“openTopContainerViewController” 覆盖bottomContainerViewController中的prepareforsegue函数
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "openTopContainerViewController" {
let instanceOfTopContainerViewController = segue.destinationViewController as! topContainerViewController
//######## HERE IS THE PROBLEM . YOU DIDN"T ASSIGN ANYTHING TO delegate variable so It became always nil to avoid it you need to assign like below
instanceOfTopContainerViewController.delegate = self
}
}
如果按代码转到topContainerViewController:请执行以下操作:(按下按钮的操作或按触发器打开topContainerViewController时保持此代码)
//First you need to give storyboard id to view controller associated with topContainerViewController then
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let instanceOfTopViewController = storyBoard.instantiateViewControllerWithIdentifier("topContainerViewControllerIdentified") as! topContainerViewController
//######## HERE IS THE PROBLEM. YOU DIDN"T ASSIGN ANYTHING TO delegate variable so It became always nil to avoid it you need to assign like below
instanceOfTopViewController.delegate = self
self.presentViewController(instanceOfTopViewController, animated: true, completion: nil)
这就是问题所在。你没有指定委托变量的任何东西所以它总是为零避免你需要像上面那样分配
答案 3 :(得分:-1)
检查代表的值是否为nil!
更改
@IBAction func sendMessage(sender: AnyObject) {
delegate!.send(textField.text!)
}
to
@IBAction func sendMessage(sender: AnyObject) {
if let delegate = delegate {
delegate.send(textField.text!)
}
}