通过Swift中的不同类调用委托方法

时间:2017-08-21 13:22:37

标签: ios swift delegates programmatically

我正在获取JSON菜单,一旦JSON返回,我想运行menuReady()来更新SomeTableViewController类中表的内容。但是下面的代码似乎不起作用。

AIM:运行 menuReady()以在JSON返回后更新内容。

问题: menuReady()永远不会被解雇。

SomeTableViewController.swift

class SomeTableViewController: UITableViewController, MenuModelDelegate {
    override func viewDidLoad() {
        menuModel.delegate = self
    }
    func menuReady() {
        // This is NOT fired.
        print("SomeViewController.menuReady()")
    }
}

MenuModel.swift

protocol MenuModelDelegate : class {
    func menuReady()
}

class MenuModel: NSObject {
    var delegate:MenuModelDelegate?
    func getMenu(data: JSON) {
        // This is fired.
        print("MenuModel.getMenu()")
        delegate?.menuReady()
    }
}

点击按钮时从AnotherViewController调用

AnotherViewController.swift

class AnotherViewController : UIViewController {
    func buttonTapped(sender: UIButton!) {
        // This function is fired.
        // jsonData is some json data returned from http request
        let menuModel = MenuModel()
        menuModel.getMenu(data: jsonData)
    }
}

2 个答案:

答案 0 :(得分:3)

委托方法旨在以一对一的方式工作。由于您在不同的地方有多个不同的MenuModel实例,因此您在此处尝试实现的关系不会起作用。您应该尝试将MenuModel初始化为SomeTableViewController的属性并使用它,如下所示:

class SomeTableViewController: UITableViewController, MenuModelDelegate {

    private let menuModel: MenuModel = MenuModel()

    override func viewDidLoad() {
        self.menuModel.delegate = self
        self.menuModel.getMenu(data: jsonData)
    }
    func menuReady() {
        print("SomeTableViewController.menuReady()")
    }
}

如果您正在寻找能够更新多个视图控制器的解决方案,那么更好的解决方案是阅读NotificationCenter。使用通知,您可以将观察者添加到多个视图控制器/类,只需让MenuModel发布通知。

https://developer.apple.com/documentation/foundation/notificationcenter

我希望有所帮助。

答案 1 :(得分:0)

感谢@PhillipMills指出委托对象应该是同一个对象实例。

以下是解决问题的方法。现在委托功能正常工作。

<强> SomeTableViewController.swift

class SomeTableViewController: UITableViewController, MenuModelDelegate {
    private let menuModel: MenuModel = MenuModel() // <--- Added property
    override func viewDidLoad() {
        menuModel.delegate = self
    }
    func menuReady() {
        print("menuReady")
    }
    // <--- Added Function
    func getModel() -> MenuModel {    
        return self.menuModel
    }
}

<强> MenuModel.swift

protocol MenuModelDelegate : class {
    func menuReady()
    func getModel() -> MenuModel
}

class MenuModel: NSObject {
    var delegate:MenuModelDelegate?
    func getMenu(data: JSON) {
        print("getMenu()")
        delegate?.menuReady()
    }
}

<强> AnotherViewController.swift

class AnotherViewController : UIViewController {
    func buttonTapped(sender: UIButton!) {
        // jsonData is some json data returned from http request
        // let menuModel = MenuModel() <--- Removed line

        /* You need to find a way to pass in someTableViewController
         * Use the menuModel defined in SomeTableViewController to
         * Call menuModel.getMenu() instead of defining a new menuModel */
        let menuModel = someTableViewController.getModel()
        menuModel.getMenu(data: jsonData)
    }
}