Generic parameter 'Value' could not be inferred creating block based KVO in swift

Viewed 3392

Entering this (contrived example) code

import Foundation

protocol ValueProviderProtocol {
    var amount: Int { get }
}

class ValueProvider: NSObject, ValueProviderProtocol {
    @objc dynamic var amount = 0
}

let _provider = ValueProvider()

var provider: ValueProviderProtocol { return _provider }

let subject = provider as! NSObject

let observer = subject.observe(\ValueProviderProtocol.amount, options: [.old, .new]) { (provider, changes) in

}

into an Xcode 9 playground, results in this error for the call to subject.observe:

Generic parameter 'Value' could not be inferred

It is not clear what is causing the error. What can be done to fix this kind of problem?

1 Answers

The following line:

let observer = subject.observe(\ValueProviderProtocol.amount, 
                               options: [.old, .new])
                               { (provider, changes) in
}

needs to change in to:

let observer = _provider.observe(\.amount,
                                 options: [.old, .new],
                                 changeHandler: { (provider, changes) in

})

You can not try to observe on subject since is downcasted to an NSObject that does not have the property amount. And second \ValueProviderProtocol.amount is a partial key path that does not infere value type \.amount is a KeyPath that inferes keypath

Related