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

Posted

技术标签:

【中文标题】通过 Swift 中的不同类调用委托方法【英文标题】:Calling delegate method through different classes in Swift 【发布时间】:2017-08-21 13:22:37 【问题描述】:

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

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

问题: 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)
    

【问题讨论】:

SomeTableViewController 中的menuModel 和“其他类”中的menuModel 是完全相同的对象吗? @PhillipMills 不,它们在单独的对象中。三个不同的对象。 那么,您授予委托的MenuModel 对象与您调用委托方法的对象相同? @PhillipMills 他们不一样。 你在哪里调用getMenu(data: JSON)方法?我假设您必须在代码中的某个地方调用它来触发委托... 【参考方案1】:

委托方法旨在以“一对一”的关系工作,因为您在不同的地方有多个不同的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

希望对你有帮助。

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于通过 Swift 中的不同类调用委托方法的主要内容,如果未能解决你的问题,请参考以下文章

UIView 类中的 Swift 集合视图委托

子类中的委托方法有时不使用 Swift 5 编译器调用

C# 一个列表中的不同类对象

UIPageViewController 不调用委托方法(Swift 5)

从 Python 中的不同类打印?

如何从现有对象的不同类调用方法(Obj C)