Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

193
Views
Weird Swift 4 closure-based KVO bug on iOS 10 devices

When I use following Swift 4 closure-based KVO way, I got a crash on iOS 10 devices

class A: NSObject {
    @objc dynamic var value: Int = 0

    var observation: NSKeyValueObservation?

    override init() {
        super.init()

        // Crash
        self.observation = self.observe(\A.value, options: [.new], changeHandler: { (_, change) in

        })
    }
}

var a: A? = A()
a = nil

Crash info:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x of class A was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x, Property: 0x>

I googled and got it was a Swift bug: https://bugs.swift.org/browse/SR-5816, and a workaround would be adding following lines inside deinit

deinit {
    if #available(iOS 11.0, *) {

    } else {
        if let observation = self.observation {
            self.removeObserver(observation, forKeyPath: "value")
        }
    }
}

My question is

  1. Why following code wouldn't crash? (Just changing observing A to observing B, which is a member of A)

    class A: NSObject {
        @objc dynamic var value: Int = 0
    
        var observation: NSKeyValueObservation?
    
        let b = B()
    
        override init() {
            super.init()
            self.observation = self.b.observe(\B.value, options: [.new], changeHandler: { (_, change) in
    
            })
        }
    }
    
    class B: NSObject {
        @objc dynamic var value: Int = 0
    }
    
    var a: A? = A()
    a = nil
    
  2. In the meanwhile, if I add previous workaround to above code, I got a new crash, why?

    deinit {
        if let observation = self.observation {
            self.b.removeObserver(observation, forKeyPath: "value")
        }
    }
    

New crash:

*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer for the key path "value" from because it is not registered as an observer.'

over 4 years ago · Santiago Trujillo
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!