未为 ChildViewController 更新父变量

Parent variable is not updated for the ChildViewController

我有一个继承自 BaseViewController.swift 的 class。我已经为核心数据更改跟踪定义了一个标志:

var coreDataUpdated: Bool?

我还在 BaseViewController.swift

viewWillAppear 中添加了核心数据更改的观察者
//Core data update
NotificationCenter.default.addObserver(self,
                                 selector: #selector(self.CoreDataUpadated),
                                 name: .NSManagedObjectContextObjectsDidChange,
                                 object: nil)

现在,每当我通知核心数据发生变化时,我都会将 coreDataUpdated 变量更改为 true

@objc func CoreDataUpadated() {
    self.coreDataUpdated = true
}

现在在我的 ChildViewController.swiftviewDidAppear 中检查 coreDataUpdated 它 returns 我 nil

这是我的完整代码:

class BaseViewController: UIViewController {
    var coreDataUpdated: Bool?

    override func viewWillAppear(_ animated: Bool) {
        //Core data update
        NotificationCenter.default.addObserver(self,
                                      selector: #selector(self.CoreDataUpadated),
                                      name: .NSManagedObjectContextObjectsDidChange,
                                      object: nil)
}

    func CoreDataUpadated() {
        self.coreDataUpdated = true
    }
}


class ChildViewController: BaseViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        reloadData()
    }

    func reloadData() {
        if super.coreDataUpdated ?? false { //I always get nil for 
            super.coreDataUpdated
            tableView?.reloadData()
        }
    }
}

注意:我正在使用 Xcode 9 beta 5 和 iOS 11 使用 swift 4。但是此代码在 Xcode 8 和 iOS 10.3 与 swift 3.

Class继承并不意味着子类实例继承超类实例中分配给属性的值。

你有一个 BaseViewController 的实例,它有一个 coreDataUpdated 属性 和一个 ChildViewController 的实例,它有一个 coreDataUpdated 属性因为它继承自 BaseViewController,但它的 属性 值与 BaseViewController 实例 属性 值无关;它们是不同的对象。

当您说 self.coreDataUpdated = true 时,您是在 BaseViewController 实例 .

上设置 属性

当您说 super.coreDataUpdated 时,您指的是 ChildViewController 实例 中的 coreDataUpdated 属性 定义它是 超类;因为这个 属性 从未被赋值所以它是 nil.

由于 ChildViewController 不会覆盖 coreDataUpdated super.coreDataUpdatedChildViewController 实例中的 self.coreDataUpdated 相同,因此您可以重写if 语句为:

func reloadData() {
    if self.coreDataUpdated ?? false { 
        tableView?.reloadData()
    }
}

希望这能让人更清楚为什么 coreDataUpdatednil

与其使用您自己的 Bool,检查 NSManagedObjectContext 实例的 hasChanges 属性 可能更简单。

感谢@Paulw11 的评论,我发现继承不会共享值。所以我使用 KVC 模式作为解决方案。这是我更改后的代码

enum coreDataState: String {
    case inserted = "inserted"
    case deleted = "deleted"
    case updated = "updated"
    var description: String {
        switch self {
        case .inserted: return "inserted"
        case .deleted: return "deleted"
        case .updated: return "updated"
        }
    }
}

class BaseViewController: UIViewController {

    override func viewWillAppear(_ animated: Bool) {
        //Core data update
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.CoreDataUpadated),
                                               name: .NSManagedObjectContextObjectsDidChange,
                                               object: nil)
    }

    func CoreDataUpdated(_ notification: Notification) {
        if let userDictionary = notification.userInfo as? Dictionary<String, Any> {
            for KV in userDictionary {
                if KV.key != "managedObjectContext" {
                    NSUserDefaultManager.SaveItem(KV.key, key: coreDataUpdateKey)
                }
            }
        }
    }

    func CoreDataChanged() -> coreDataState? {
        if let currentState = NSUserDefaultManager.LoadItem(coreDataUpdateKey) as? String {
            NSUserDefaultManager.RemoveItem(coreDataUpdateKey)
            return coreDataState(rawValue: currentState)
        }
        return nil
    }
}


class ChildViewController: BaseViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        reloadData()
    }

    func reloadData() {
        if super.CoreDataChanged() != .deleted {
            loadData()

            tableView?.reloadData()
        }
    }
}

尽管可以使用其他模式来实现它,例如 delegateoverride 子 类

中的 CoreDataUpdated 函数