使用didSet使函数多次运行

时间:2019-02-07 20:09:37

标签: ios swift swift4 viewcontroller

为了从先前的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次。但是,如果我从configureView()中删除对viewWillAppear()的呼叫,则该视图将不会出现。如果我将其从didSet中删除,则detailBuilding的值(例如detailBuilding.rating)将为nil。尽管函数第三次运行,但detailBuilding的值始终始终为零,这意味着我无法使用它们。

在先前的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在3次中的第3次为零。并且我应该使用其他方法来获取detailBuilding,因为我需要它包含在NSPredicate中的值。

谢谢。

2 个答案:

答案 0 :(得分:2)

您正在创建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)

答案 1 :(得分:1)

在您刚刚提供的代码中,应该仅一个两次调用configureView()

    在执行didSet之后立即由controller.detailBuilding = detailBuilding制成的
  1. 在对象初始化后由viewDidLoad制成

话虽如此,您需要提供更多代码,尤其是:

viewWillAppear()(来自ReviewViewController)和触发显示ReviewViewController的代码。

编辑:

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

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

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

这就是为什么您拥有nil的原因。您正在显示的品牌ViewController与注入detailBuilding的品牌无关。

这就是为什么您有3次调用configureView()方法的原因:

  1. 类型为controller的{​​{1}}的
  2. viewDidLoad
  3. 从注入(didSet)
  4. 类型为ReviewViewController的未命名对象的viewDidLoad,未注入任何内容,因此在第3次调用时在ReviewViewController中插入了nil