【问题标题】:Protocol-Delegate pattern not notifying View Controller协议委托模式不通知视图控制器
【发布时间】:2022-02-19 06:46:09
【问题描述】:

我的Model 将数据保存到 Firestore。保存该数据后,我希望它提醒我的ViewController,以便可以调用函数。但是,没有任何东西传递给我的ViewController

这是我的Model

protocol ProtocolModel {
    func wasDataSavedSuccessfully(dataSavedSuccessfully:Bool)
}

class Model {

    var delegate:ProtocolModel?

    func createUserAddedRecipe(
        docId:String,
        completion: @escaping (Recipe?) -> Void) {

            let db = Firestore.firestore()

                do {
                    try db.collection("userFavourites").document(currentUserId).collection("userRecipes").document(docId).setData(from: recipe) { (error) in

                        print("Data Saved Successfully") // THIS OUTPUTS TO THE CONSOLE
                        
                        // Notify delegate that data was saved to Firestore
                        self.delegate?.wasDataSavedSuccessfully(dataSavedSuccessfully: true)
                     }
                }
                catch {
                    print("Error \(error)")
                }
    }
}

print("Data Saved Successfully") 输出到控制台,但它下面的委托方法没有被调用。

这是我的ViewController

class ViewController: UIViewController {
    
    private var model = Model()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        model.delegate = self
    }
}

extension ViewController: ProtocolModel {
    func wasDataSavedSuccessfully(dataSavedSuccessfully: Bool) {
        if dataSavedSuccessfully == true {
            print("Result is true.")
        }
        else {
            print("Result is false.")
        }
        
        print("Protocol-Delegate Pattern Works")
    }
}

这个模式有什么我遗漏的吗?我没有注意到我所评论的文章有什么不同。

【问题讨论】:

  • 您不应该在catch 中调用您的委托方法吗?您还应该将该委托属性设为weak,但这是一个单独的主题。
  • 你打电话给createUserAddedRecipe。我建议将 let db = Firestore.firestore() 存储为模型的属性
  • 不知道你在哪里调用 createUserAddedRecipe 方法?
  • 我测试了类似你的代码的东西,一切都像魅力一样,如果你愿意,我可以与你分享
  • @RezaKhonsari 我很想看看你的例子!

标签: ios swift model-view-controller delegates protocols


【解决方案1】:

所以我测试你的代码并模拟类似的东西

import UIKit

protocol ProtocolModel {
    func wasDataSavedSuccessfully(dataSavedSuccessfully:Bool)
}

class Model {
    
    var delegate:ProtocolModel?
    
    // I use this timer for simulate that firebase store data every 3 seconds for example
    var timer: Timer?
    
    func createUserAddedRecipe(
        docId:String) {
            
            timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true, block: { _ in
                self.delegate?.wasDataSavedSuccessfully(dataSavedSuccessfully: true)
            })
        }
}

class NavigationController: UINavigationController {
    
    var model = Model()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        model.delegate = self
        // Call this method to register for network notification
        model.createUserAddedRecipe(docId: "exampleId")
    }
}

extension NavigationController: ProtocolModel {
    func wasDataSavedSuccessfully(dataSavedSuccessfully: Bool) {
        print(#function)
    }
}

所以您可以看到如下图所示的结果,我的委托更新控制器符合该协议。

【讨论】:

  • 非常感谢@RezaKhonsari!您的示例帮助我发现我正确设置了我的协议委托模式。如果我在 ViewController 的viewDidLoad() 中调用委托,我的委托方法就会被调用。但是如果我在 ViewController 的@IBAction func 中调用它,它不会被调用。你知道为什么会这样吗?
  • 更新:它实际上在我的@IBAction func 中工作。在我的Modelsome 函数中调用它时不起作用。我会继续挖掘。
  • 哇,这是一个非常愚蠢的错误。我打电话给Model().function()。当我将其更改为 model = Model()model.function() 时,它起作用了。非常感谢您的指导!
  • @amirbt17 不客气,如果我的回答对您有帮助,能否请您将我的回答标记为正确并点赞。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多