-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added NSObject+JKSObserving for simple predictable block based KVO
- Loading branch information
Showing
4 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// JKSObserving.h | ||
// Frames | ||
// | ||
// Created by Johan Sørensen on 10/11/12. | ||
// Copyright (c) 2012 Johan Sørensen. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
typedef void(^JKSObservingHandlerBlock)(id observedObject, NSDictionary *change); | ||
|
||
@interface JKSObserving : NSObject | ||
@property (strong, readonly) NSString *keyPath; | ||
@property (weak, readonly) id observable; | ||
|
||
+ (JKSObserving *)observingWithObject:(id)object | ||
keyPath:(NSString *)keyPath | ||
options:(NSKeyValueObservingOptions)options | ||
handler:(JKSObservingHandlerBlock)handlerBlock; | ||
- (instancetype)initWithObject:(id)object | ||
keyPath:(NSString *)keyPath | ||
options:(NSKeyValueObservingOptions)options | ||
handler:(JKSObservingHandlerBlock)handlerBlock; | ||
@end | ||
|
||
|
||
@interface NSObject (JKSObservingAdditions) | ||
/** Adds an observer for the keyPath | ||
* | ||
* @discussion The caller is responsible for controlling the lifetime of the observing, eg. deallocate | ||
* the returned JKSObserving when the observing is no longer needed/wanted | ||
*/ | ||
- (JKSObserving *)jks_observingForKeyPath:(NSString *)keyPath | ||
options:(NSKeyValueObservingOptions)options | ||
handler:(JKSObservingHandlerBlock)handlerBlock; | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// | ||
// JKSObserving.m | ||
// Frames | ||
// | ||
// Created by Johan Sørensen on 10/11/12. | ||
// Copyright (c) 2012 Johan Sørensen. All rights reserved. | ||
// | ||
|
||
#import "NSObject+JKSObserving.h" | ||
#import <objc/runtime.h> | ||
|
||
static void *JKSObservingKVOContext = &JKSObservingKVOContext; | ||
|
||
@interface JKSObserving () | ||
@property (copy) JKSObservingHandlerBlock handler; | ||
@end | ||
|
||
@implementation JKSObserving | ||
+ (JKSObserving *)observingWithObject:(id)object | ||
keyPath:(NSString *)keyPath | ||
options:(NSKeyValueObservingOptions)options | ||
handler:(JKSObservingHandlerBlock)handlerBlock | ||
{ | ||
return [[JKSObserving alloc] initWithObject:object keyPath:keyPath options:options handler:handlerBlock]; | ||
} | ||
|
||
|
||
- (instancetype)initWithObject:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options handler:(JKSObservingHandlerBlock)handlerBlock | ||
{ | ||
NSParameterAssert(keyPath); | ||
NSParameterAssert(handlerBlock); | ||
|
||
if ((self = [super init])) { | ||
_keyPath = keyPath; | ||
_handler = [handlerBlock copy]; | ||
_observable = object; | ||
[object addObserver:self forKeyPath:keyPath options:options context:JKSObservingKVOContext]; | ||
} | ||
return self; | ||
} | ||
|
||
|
||
- (void)dealloc | ||
{ | ||
[_observable removeObserver:self forKeyPath:_keyPath context:JKSObservingKVOContext]; | ||
} | ||
|
||
|
||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context | ||
{ | ||
if (context == JKSObservingKVOContext) { | ||
self.handler(self.observable, change); | ||
} else { | ||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; | ||
} | ||
} | ||
|
||
@end | ||
|
||
|
||
//NSString *const kAssociatedObservingsKey = @"kAssociatedObservingsKey"; | ||
@implementation NSObject (JKSObservingAdditions) | ||
- (JKSObserving *)jks_observingForKeyPath:(NSString *)keyPath | ||
options:(NSKeyValueObservingOptions)options | ||
handler:(JKSObservingHandlerBlock)handlerBlock | ||
{ | ||
JKSObserving *observing = [JKSObserving observingWithObject:self keyPath:keyPath options:options handler:handlerBlock]; | ||
return observing; | ||
} | ||
|
||
|
||
//- (void)jks_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options handler:(JKSObservingHandlerBlock)handlerBlock | ||
//{ | ||
// // TODO: raise if already added? | ||
// JKSObserving *observer = [JKSObserving observingWithObject:self keyPath:keyPath options:options handler:handlerBlock]; | ||
// [[self jks_observings] addObject:observer]; | ||
//} | ||
// | ||
//// Big issue: associated objects area cleared after normal dealloc as part of object_dispose() (see WWDC 2011 session 322 (around 37:35)) | ||
//// Which means -[JKSObserving dealloc] is called too late and the KVO machinery spews a warning to the console | ||
//- (NSMutableSet *)jks_observings | ||
//{ | ||
// NSMutableSet *observings = objc_getAssociatedObject(self, &kAssociatedObservingsKey); | ||
// | ||
// if (!observings) { | ||
// observings = [[NSMutableSet alloc] init]; | ||
// objc_setAssociatedObject(self, &kAssociatedObservingsKey, observings, OBJC_ASSOCIATION_RETAIN); | ||
// } | ||
// | ||
// return observings; | ||
//} | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters