未更新ChildViewController

时间:2017-08-22 07:19:17

标签: ios xcode nsnotificationcenter swift4

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

var coreDataUpdated: Bool?

我还在viewWillAppear的{​​{1}}

中添加了核心数据更改观察员
BaseViewController.swift

现在每当我通知核心数据的变化时,我都会将//Core data update NotificationCenter.default.addObserver(self, selector: #selector(self.CoreDataUpadated), name: .NSManagedObjectContextObjectsDidChange, object: nil) 变量更改为coreDataUpdated

true

现在,在我@objc func CoreDataUpadated() { self.coreDataUpdated = true } ChildViewController.swift viewDidAppear检查coreDataUpdated时,它会返回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()
        }
    }
}

注意:我正在使用swift 4处理Xcode 9 beta 5和iOS 11.但是这个代码在Xcode 8和iOS 10.3上使用swift 3工作正常。

2 个答案:

答案 0 :(得分:1)

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

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

当您说self.coreDataUpdated = true时,您要在BaseViewController 实例上设置该属性。

当您说super.coreDataUpdated时,您指的是由{em>超类定义的coreDataUpdated 实例中的ChildViewController属性;由于此属性从未被赋值为nil

由于ChildViewController未覆盖coreDataUpdated super.coreDataUpdatedself.coreDataUpdated实例中的ChildViewController相同,因此您可以重写if func reloadData() { if self.coreDataUpdated ?? false { tableView?.reloadData() } } 1}}声明为:

coreDataUpdated

希望这更清楚地表明为什么nilBool

检查hasChanges实例的NSManagedObjectContext属性可能更简单,而不是使用您自己的var op_prod_id = $(this).data('id');

答案 1 :(得分:0)

感谢@ 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函数来实现它