Search code examples
swiftkey-value-observingnsoperationqueue

Swift 4 KVO fatal error during operations observing


I am trying to observe OperationQueue operations count using KVO in Swift 4 but get fatal error on operations array changing.

The following code is used in playground:

import Foundation

class MyObjectToObserve:NSObject {
    @objc dynamic var queue = OperationQueue()
}

class MyObserver:NSObject {

    @objc var objectToObserve: MyObjectToObserve
    var observation: NSKeyValueObservation?

    init(object: MyObjectToObserve) {
        objectToObserve = object
        super.init()

        observation = observe(\.objectToObserve.queue.operations.count) { object, change in
            print("Observed")
        }
    }
}

let myObjectToObserve = MyObjectToObserve()
let myObserver = MyObserver(object: myObjectToObserve)

myObjectToObserve.queue.addOperation {
    print("First operation")
    }

This error:

Fatal error: Could not extract a String from KeyPath Swift.KeyPath<__lldb_expr_6.MyObserver, Swift.Int>: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.74.1/src/swift/stdlib/public/SDK/Foundation/NSObject.swift, line 85

As I understand the problem is that OperationQueue operations is Swift array and KVO can't work with it. I tried to use array with integers instead of OperationQueue and get the same error. How to observe OperationQueue operations properly in Swift 4 or is there another way to get notification when OperationQueue finishes all tasks?


Solution

  • You cannot observe the count property of an array. You cannot observe any property of an array:

    NSArray objects are not observable, so this method raises an exception when invoked on an NSArray object.

    OperationQueue has a separate operationCount property for you to observe instead.

        observation = observe(\.objectToObserve.queue.operationCount) { object, change in
            print("Observed")
        }