I'm experimenting with the observer introduced by Swift 4. Here's a snippet of code I've been playing with:
> import Cocoa
>
> typealias StockPrice = Int
>
> class Stock: NSObject {
> let symbol: String
> @objc dynamic var price: StockPrice = 0
>
> init(symbol: String) {
> self.symbol = symbol
> }
>
> func update(price: StockPrice) {
> self[keyPath: \.price] = price
> }
> }
>
> class StockWatcher: NSObject {
> @objc var stock: Stock
>
> var observersation: NSKeyValueObservation?
>
> init(stock: Stock) {
> self.stock = stock
> super.init()
>
> observersation = observe(\.stock.price, options: [.old, .new]) {
> object, change in
> print("\(stock.symbol) changed from \(change.oldValue!) to \(change.newValue!)")
> }
> }
> }
>
> var aapl = Stock(symbol: "appl")
> aapl.update(price: 171)
> var watcher = StockWatcher(stock: aapl)
> aapl.update(price: 190)
This code works as expected. However, when I change the definition of StockPrice to Decimal, I receive the followed unhandled exception:
> 2019-03-11 15:23:21.816057-0400 KeyPath[8868:4286496] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSMethodSignature signatureWithObjCTypes:]: unsupported type encoding spec '{?}''
> *** First throw call stack:
> (
> 0 CoreFoundation 0x00007fff4630fded __exceptionPreprocess + 256
> 1 libobjc.A.dylib 0x00007fff723db720 objc_exception_throw + 48
> 2 CoreFoundation 0x00007fff46263571 +[NSMethodSignature signatureWithObjCTypes:] + 2413
> 3 CoreFoundation 0x00007fff462b1617 ___forwarding___ + 389
> 4 CoreFoundation 0x00007fff462b1408 _CF_forwarding_prep_0 + 120
> 5 KeyPath 0x0000000100006f15 $s7KeyPath5StockC5priceSo9NSDecimalavpACTk + 229
> 6 libswiftCore.dylib 0x0000000100497d63 $ss26NonmutatingWritebackBufferCfD + 67
> 7 libswiftCore.dylib 0x000000010063d550 _swift_release_dealloc + 16
> 8 KeyPath 0x0000000100006d53 $s7KeyPath5StockC6update5priceySo9NSDecimala_tF + 371
> 9 KeyPath 0x00000001000046ce main + 11566
> 10 libdyld.dylib 0x00007fff734a9ed9 start + 1
> 11 ??? 0x0000000000000001 0x0 + 1
> )
> libc++abi.dylib: terminating with uncaught exception of type NSException
Are there restrictions concerning the type being observed?
tkrajacic
(Thomas Krajacic)
2
If you change it to NSDecimalNumber it should work I guess.
Decimal is a struct which cannot be observed. And it doesn't automatically bridge to NSDecimalNumber iirc
Yes, defining StockPrice as NSDecimalNumber worked fine.
You mentioned that Decimal is a structure, which cannot be observed. However, defining StockPrice as Int works fine, and Int is a structure.
Are there rules that dictate what can be observed?
1 Like