This is the 11th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Hi 👋

  • Wechat: RyukieW
  • 📦 Technical article archive
  • 🐙 making
My personal project Mine Elic endless sky ladder Dream of books
type The game financial
AppStore Elic Umemi

preface

KVO is often used in development, but there are hidden corners that are often overlooked, and this article will explore some of those corners.

⚠️ Important Notes

Important: In order to understand key-value observing, you must first understand key-value coding.

Important: In order to understand KVO, you must first understand KVC. Recommended reading: IOS-KVC detailed explanation

A, the Options

It affects the contents of the change dictionary provided in the notification and how the notification is generated.

NSKeyValueObservingOptionOld

Change the previous value

NSKeyValueObservingOptionNew

Receive the new value

NSKeyValueObservingOptionInitial

Your instructions immediately change notification that is sent by the observation object using option NSKeyValueObservingOptionInitial (in addObserver: forKeyPath: options: context: before returns). You can use this additional one-time notification to get the initial value.

NSKeyValueObservingOptionPrior

You can include option NSKeyValueObservingOptionPrior instructions were observed before the property change notifications (in addition to change usually notice).

Change dictionary by including key NSKeyValueChangeNotificationIsPriorKey and contains YES NSNumber values change notification in advance.

Multiple can be received through a bitwise enumeration of these options

Second, the Context

[tool.ryuk addObserver:tool forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL];
Copy the code

In normal use, we usually pass NULL but what is it really doing?

AddObserver: forKeyPath: options: context: in the message context pointer can contain any data, these data will be passed back to the observer in the corresponding change notification. You can specify NULL and rely entirely on the key path string to determine the source of the change notification, but this approach can cause an object’s parent class to have problems observing the same key path for different reasons.

A more secure and extensible approach is to use Context to ensure that the notifications you receive are sent to your observers and not to the superclass.

The address of the uniquely named static variable in the class is a nice Context. Contexts selected in a similar manner in a parent or child class are unlikely to overlap. You can select a Context for the entire class and rely on the critical path string in the notification message to determine what has changed.

Alternatively, you can create a different Context for each observed key path, bypassing string comparisons altogether and improving notification parsing.

createContextPointer to the

static void *PersonAccountBalanceContext = &PersonAccountBalanceContext;
static void *PersonAccountInterestRateContext = &PersonAccountInterestRateContext;
Copy the code

Registered observer

- (void)registerAsObserverForAccount:(Account*)account {
    [account addObserver:self
              forKeyPath:@"balance"
                 options:(NSKeyValueObservingOptionNew |
                          NSKeyValueObservingOptionOld)
                 context:PersonAccountBalanceContext];
 
    [account addObserver:self
              forKeyPath:@"interestRate"
                 options:(NSKeyValueObservingOptionNew |
                          NSKeyValueObservingOptionOld)
                  context:PersonAccountInterestRateContext];
}
Copy the code

Observation of mutable arrays

KVO relative to a mutable array would probably write something like this. But obviously it doesn’t work. In order to understand KVO, you must first understand KVC.

The API needs to be adjusted in order to enable changes within the mutable Collection to be heard

  • mutableArrayValueForKey: and mutableArrayValueForKeyPath:
    • return NSMutableArray
  • mutableSetValueForKey: and mutableSetValueForKeyPath:
    • return NSMutableSet
  • mutableOrderedSetValueForKey: and mutableOrderedSetValueForKeyPath:
    • return NSMutableOrderedSet

Four, KVO switch control

If you write a library and you don’t want some of the properties inside to be listened on. Is there any way to stop it?

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;
Copy the code

The system provides the above method, which returns YES by default, meaning that all properties can be listened on. You can return NO if you don’t want some or all of them to be listened on.

4.1 Prohibit All

There is no notification to trigger the change

4.2 Partial Prohibition

The name notification did not trigger, the books notification did.

4.3 Manually Sending a Notification after being Disabled

Although automaticallyNotifiesObserversForKey banned notice, but can still listen to normal after manually triggered

reference

  • Key-Value Observing Programming Guide
  • Key-Value Coding Programming Guide