导航堆栈之前视图之间的协议委托
Posted
技术标签:
【中文标题】导航堆栈之前视图之间的协议委托【英文标题】:Protocol delegate between view before navigation stack 【发布时间】:2020-01-29 09:53:34 【问题描述】:View1
转至 导航控制器 - View2
转至 View3
我正在尝试创建从 View3 到 View1 的协议委托
在视图1
class NormalUser: UIViewController, NormalUserDelegate
@objc func showAddressView()
addressView.isHidden = false
override func viewDidLoad()
super.viewDidLoad()
if let conn = self.storyboard?.instantiateViewController(withIdentifier: "View") as? View
conn.delegate = self
在视图3中
weak var delegate: NormalUserDelegate?
func test()
self.delegate?.showAddressView()
协议
protocol NormalUserDelegate: class
func showAddressView()
我无法让它工作。有什么想法吗?
【问题讨论】:
我想在这种情况下最好使用 NSnotifications 您没有得到答案的原因是您的问题根本不清楚。不要让我们破译你的代码来弄清楚你想问什么,并给我们更多关于你是如何失败的信息,而不是“我无法让它工作”。此外,视图控制器不是视图,因此称它们为“View1”和“View3”只会让您的问题更难理解。 在您的示例中,conn
在viewDidLoad
之后超出范围。 View3 的delegate
成员被标记为weak
,因此当viewDidLoad
返回时,对它的引用会丢失。要使您的代码正常工作,您必须使 conn
成为 View1 类的成员,或者删除 View3 的 delegate
成员上的 weak
关键字。
@UtkuDalmaz,请分享一个演示项目,它重现了您面临的相同问题。
【参考方案1】:
在我看来,您有 2 个不错的选择来使用委托模式。 1个糟糕的选择,但它很笨拙和懒惰,然后你就有了广播接收器模式。
2 个不错的选择
1 - 向前传递委托
class VC1: UIViewController, SomeDelegate
func delegateFunction()
func showNextVC()
let next = VC2()
next.forwardingDelegate = self
present(next, animated: true)
class VC2: UIViewController
var forwardingDelegate: SomeDelegate? = nil
func showNextVC()
let next = VC3()
next.delegate = forwardingDelegate
present(next, animated: true)
2 - 将第三个控制器传递给第二个控制器
class VC1: UIViewController, SomeDelegate
func delegateFunction()
func showNextVC()
let final = VC3()
final.delegate = self
let next = VC2(withControllerToPresent: final)
present(next, animated: true)
class VC2: UIViewController
let controller: UIViewController
init(withControllerToPresent controller: UIViewController)
self.controller = controller
super.init(withNibName: nil, bundle: nil
func showNextVC()
present(controller, animated: true)
class VC3: UIViewController
var delegate: SomeDelegate? = nil
1 可怕的选择
使用单例/全局变量....(请不要)
个人意见
我已经完成了前两个选项...它们有效。但是广播接收器模式可能更好,因为它会更干净。 VC2 不需要向 3 转发任何内容。只要确保您的通知命名空间足够具体,以后不会被其他任何东西捕获。
【讨论】:
注意,这不使用情节提要。 虽然我认为你仍然可以这样做,只需将文件中的属性设置为 IBoutlet 并将它们连接到故事板中【参考方案2】:如果我正确理解您的场景,您需要两个委托,每个委托将数据传递回之前的 UIViewController。据我所知,您无法绕过辅助 UIViewController。
【讨论】:
【参考方案3】:您缺少的是一个路由器类,这是我如何实现它的一个简单示例。
protocol RoutingView1
func openView2()
protocol RoutingView2
func openView3()
protocol RoutingView3
func foo()
class View1
func foo()
//this will get called when View3 calls its RootingView3.foo()
class Router: RoutingView1, RoutingView2
var rootView: View1
func start() -> UIViewController
view.routingDelegate = self
rootView = view1
func openView2()
let vc = View2()
vc.routingDelegate = self
rootView.push()
func openView3()
let vc = View3()
vc.routingDelegate = self
rootView.push()
func foo()
rootView.foo()
【讨论】:
【参考方案4】:放松转场
如果您使用的是界面生成器,则使用展开转场可能是最简单/最干净的。
在 VC1 中创建界面构建器操作:
class VC1: UIViewController
@IBAction func backToVC1(_ segue: UIStoryboardSegue)
self.showAddress()
func showAddress()
addressView.isHidden = false
在您的 VC3 故事板中,按住控件并单击视图控制器图标,将鼠标拖到退出图标上并释放。单击以选择您在 VC1 中创建的展开转场。
创建转场后,在文档大纲中选择它。
并在属性检查器中命名。
最后,在你的 VC3 代码中调用 segue。
class VC3: UIViewController
func test()
self.performSegue(withIdentifier: "unwindToVC1", sender: self)
【讨论】:
【参考方案5】:我认为您可以在这种情况下使用SwiftEventBus
。 Link
示例:
@IBAction func clicked(sender: AnyObject)
count++
SwiftEventBus.post("doStuffOnBackground")
@IBOutlet weak var textField: UITextField!
var count = 0
override func viewDidLoad()
super.viewDidLoad()
SwiftEventBus.onBackgroundThread(self, name: "doStuffOnBackground") notification in
println("doing stuff in background thread")
SwiftEventBus.postToMainThread("updateText")
SwiftEventBus.onMainThread(self, name: "updateText") notification in
self.textField.text = "\(self.count)"
//Perhaps on viewDidDisappear depending on your needs
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
SwiftEventBus.unregister(self)
【讨论】:
【参考方案6】:**Just set delegate of view 2 as a delegate of view 3 as below:**
class View1: UIViewController, NormalUserDelegate
@objc func showAddressView()
addressView.isHidden = false
// Going to view 2 by any means i.e segue , navigation set
func goToView2Controller()
if let view2 = self.storyboard?.instantiateViewController(withIdentifier: "View2") as? View2
view2.delegate = self
self.navigationController?.pushViewController(view2, animated: true)
class View2: UIViewController
weak var delegate: NormalUserDelegate?
// Going to view 3 by any means i.e segue or other means
func goToView3Controller()
if let view3 = self.storyboard?.instantiateViewController(withIdentifier: "View3") as? View3
view3.delegate = self.delegate
self.navigationController?.pushViewController(view3, animated: true)
class View3: UIViewController
weak var delegate: NormalUserDelegate?
func test()
self.delegate?.showAddressView()
【讨论】:
以上是关于导航堆栈之前视图之间的协议委托的主要内容,如果未能解决你的问题,请参考以下文章