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

Calling delegate method through different classes in Swift

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

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)
    }
}

委托方法设计用于在 "one on one" 关系中工作,您在此处尝试实现的是行不通的,因为您在不同的地方有多个不同的 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。使用通知,您可以将观察者添加到多个视图 controllers/classes 并简单地让您的 MenuModel 到 post 收到通知。

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

希望对您有所帮助。

感谢@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)
    }
}