使用 didSet 导致函数 运行 多次

Using didSet causes function to be run multiple times

为了从之前的 viewController 中获取值,我在结构上使用了 didSet

class ReviewViewController:  UIViewController, UITextFieldDelegate {
var detailBuilding: Building? {
    didSet {
        configureView()
    }

}

override func viewDidLoad() {
    super.viewDidLoad()
    configureView()
    CKContainer.default()

}

override func viewWillAppear(_ animated: Bool) {
    print("this override ran")
    navigationItem.hidesBackButton = false

}

func configureView() {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "RatingAttributes")
    print("the buildingID is \(String(describing: detailBuilding?.buildingID))")

    request.predicate = NSPredicate(format: "buildingID == %@", String(describing: detailBuilding?.buildingID))
    print("configuration ran")
    do {
        let result = try context.fetch(request)
        //assert(result.count < 2)
        //print("the result we got was \(result[0])")
        for data in result as! [NSManagedObject] {
            print("The data was \(data.value(forKey: "buildingID")) ")
        }
    } catch {

        print("Failed to retreive core data")
    }
}

}

但是,使用 func configureView() 中的 print 语句,我可以看出该函数运行了 3 次。但是,如果我从 viewWillAppear() 中删除对 configureView() 的调用,那么视图将不会出现;如果我从 didSet 中删除它,那么 detailBuilding 的值(例如 detailBuilding.rating)将为零。尽管该函数第三次运行,但 detailBuilding 的值始终为 nil,这意味着我无法使用它们。

在之前的viewController我有:

@objc func addReviewAction(_ sender: UIButton) {
    print("ran this correctly")
    //navigationController?.setNavigationBarHidden(true, animated: true)
    let controller = ReviewViewController()
    controller.detailBuilding = detailBuilding
    controller.navigationItem.title = ""
    navigationItem.hidesBackButton = true
    let backItem = UIBarButtonItem()
    backItem.title = ""
    backItem.tintColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
    navigationController?.navigationItem.backBarButtonItem = backItem
    navigationController?.pushViewController(ReviewViewController(), animated: true)

}

我已经多次检查以确保我没有从其他任何地方不小心调用 configureView()。

我的问题是:为什么 configureView() 运行 多次?为什么 detailBuilding nil 在 3 次中的第 3 次。我是否应该使用不同的方法来获取 detailBuilding,因为我需要它为我的 NSPredicate 包含的值。

谢谢。

根据您刚刚提供的代码,应该只有 一个 两次调用 configureView()

  1. didSet 生成,紧接着 controller.detailBuilding = detailBuilding 被执行。

  2. 在对象初始化后从 viewDidLoad 生成

也就是说,您需要提供更多代码,尤其是:

viewWillAppear() 来自 ReviewViewController 和触发显示 ReviewViewController.

的代码

编辑:

感谢您提供更多详细信息:)

您遇到问题: navigationController?.pushViewController(ReviewViewController(), animated: true)

应该是 navigationController?.pushViewController(controller, animated: true)

这就是您 nil 的原因。您现在展示的品牌 ViewController 与注入 detailBuilding 的品牌无关。

这就是为什么你调用了 3 次 configureView() 方法:

  1. controllerReviewViewController
  2. 类型的 viewDidLoad
  3. 来自注入(didSet)
  4. ReviewViewController 类型的未命名对象的 viewDidLoad,没有注入任何内容,因此在第 3 次调用时 detailBuilding 里面有 nil

您正在创建 ReviewViewController 的两个实例,并且仅在其中一个实例上设置了详细信息

// 1st instance
let controller = ReviewViewController() 
controller.detailBuilding = detailBuilding
controller.navigationItem.title = ""
navigationItem.hidesBackButton = true
let backItem = UIBarButtonItem()
backItem.title = ""
backItem.tintColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
navigationController?.navigationItem.backBarButtonItem = backItem

// 2nd instance, first is deallocated and never used.
navigationController?.pushViewController(ReviewViewController(), animated: true)
// replace with:
navigationController?.pushViewController(controller, animated: true)