Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Swift 4, how do I remove a block-based KVO observer?

If I store an observer like this:

let observer: NSKeyValueObservation = foo.observe(\.value, options: [.new]) { (foo, change) in     print(change.newValue) } 

How do I remove/disable/cleanup observer once I no longer need it?

My foo instance does not have any remove-like method that receives an NSKeyValueObservation instance, the observer itself doesn't have any remove-like either.

like image 467
Guilherme Avatar asked Oct 05 '17 17:10

Guilherme


People also ask

What is KVO key-value observation)?

KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. The concept is simple: when we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables.

How to use observer in swift?

Observer is a behavioral design pattern that allows some objects to notify other objects about changes in their state. The Observer pattern provides a way to subscribe and unsubscribe to and from these events for any object that implements a subscriber interface.

Can you explain KVO and How it's used on apple's platforms?

Key-value observing is a Cocoa programming pattern you use to notify objects about changes to properties of other objects. It's useful for communicating changes between logically separated parts of your app—such as between models and views. You can only use key-value observing with classes that inherit from NSObject .


2 Answers

In iOS 11, you don't have to. Just let the observer go out of scope. There is no penalty any longer for letting an observer die before the observed or for letting the observed die before the observer, so you have no actual work to do.

On the other hand, if you really want to unregister the observer, remove it from whatever is retaining it, or tell it to invalidate. (Something must be retaining it, because if you don't persist the observer, it will die and your observer function will never be called.)

(You say "if I store an observer like this", but the way you are storing it, with let, is a somewhat silly way to store the observer. It would be better to put it in a Set from which you can remove it later, or at least store it in a Optional var that you can later set to nil.)

like image 110
matt Avatar answered Sep 20 '22 12:09

matt


With Swift 5, I began using .observe(\.propertyName, ...) on core data objects as the tokens automatically unregister at deinit or an invalidate() call on the token.

This works remarkably well until I recently noticed that I was leaking objects. I was seeing leaked NSKeyValueObservance, NSKeyValueObservationInfo, and NSArray objects. After verifying that I was managing the tokens properly, I finally tracked down the problem.

If you perform an .observe() on a Core Data object, you must keep the object as well as the token. If the object turns into a fault before you invalidate/release the token, you will leak memory. You do not crash but once it turns into a fault you will leak memory even if you free the token.

like image 29
dlemex Avatar answered Sep 19 '22 12:09

dlemex