JVI
JVI

Reputation: 63

Cocoa Binding (Enabled) broken after updating to Swift4

I am trying to update my codes from Swift3.3 to Swift4.1 but encountering KVC error.
Swift4CocoaBindings[4639:2311856] [General] [<Swift4CocoaBindings.AppDelegate 0x604000000270> addObserver:<NSKeyValueObservance 0x60c000045e50> forKeyPath:@"dbCom.dbFileExists" options:256 context:0x0] was sent to an object that is not KVC-compliant for the "dbCom" property.

What I'm doing is disabling menu items depending on properties' value in my singleton class (DBCom.swift), which is inherited from NSObject.

So I created blank projects, one with Swift3.3 and the other with Swift4.1, both with same DBCom.swift, to see if this problem reproduced. And found it reproduced.

In AppDelegate.swift, I included the singleton as follows.
let dbCom = DBCom.shared

Then,
Bindings of menu items are made to Enabled with self.dbCom.dbFileExists in the InterfaceBuilder. This was working with Swift3.3 but once it is switched to Swift4.1, the app got the error at the startup.

dbFileExists' implementation in the DBCom.swift is as follows. Just checking the file is existed or not.

var dbFileExists: Bool {
    get {
        if let dbfp = dbFullPath {
            if FileManager.default.fileExists(atPath: dbfp.path) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }
}

If anyone can suggest the solution to this problem, it'd be very much appreciated.

Regards,

Upvotes: 0

Views: 178

Answers (1)

OOPer
OOPer

Reputation: 47876

Cocoa Binding depends on the dynamic features of Objective-C, such as KVC/KVO.

So, all the properties included in the Cocoa Binding reference needs to be Objective-C compatible.

Try adding @obc explicitly:

@objc let dbCom = DBCom.shared

and:

@objc dynamic var dbFileExists: Bool {
    get {
        if let dbfp = dbFullPath {
            if FileManager.default.fileExists(atPath: dbfp.path) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }
}

Since Swift 4, automatic annotation of @objc happens in very limited conditions and you may need to explicitly annotate each properties or methods.

Upvotes: 1

Related Questions