Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Created April 28, 2012 19:18
Show Gist options
  • Save kristopherjohnson/2521453 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/2521453 to your computer and use it in GitHub Desktop.
Invokes a block when an observed KVO property changes
// Copyright (C) 2012 Kristopher Johnson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
typedef void (^KJPropertyChangeBlock)(id newValue);
// Object that invokes a block when a specified property is changed for an observed object
@interface KJPropertyObserver : NSObject
@property (nonatomic, readonly) NSObject *subject;
@property (nonatomic, readonly, copy) NSString *keyPath;
@property (nonatomic, readonly, copy) KJPropertyChangeBlock changeBlock;
// Return an observer for the specified key path on the specified object
+ (KJPropertyObserver *)observerForKeyPath:(NSString *)keyPath ofSubject:(NSObject *)subject onChange:(KJPropertyChangeBlock)changeBlock;
// Initialize observation for the specified key path on the specified object
- (id)initObservingKeyPath:(NSString *)keyPath ofSubject:(NSObject *)subject onChange:(KJPropertyChangeBlock)changeBlock;
@end
// Copyright (C) 2012 Kristopher Johnson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "PropertyObserver.h"
@interface KJPropertyObserver ()
@property (nonatomic, readwrite) NSObject *subject;
@property (nonatomic, copy, readwrite) NSString *keyPath;
@property (nonatomic, copy, readwrite) KJPropertyChangeBlock changeBlock;
@end
@implementation KJPropertyObserver
@synthesize subject = _subject;
@synthesize keyPath = _keyPath;
@synthesize changeBlock = _changeBlock;
+ (KJPropertyObserver *)observerForKeyPath:(NSString *)keyPath ofSubject:(NSObject *)subject onChange:(KJPropertyChangeBlock)changeBlock {
return [[KJPropertyObserver alloc] initObservingKeyPath:keyPath ofSubject:subject onChange:changeBlock];
}
- (id)initObservingKeyPath:(NSString *)keyPath ofSubject:(NSObject *)subject onChange:(KJPropertyChangeBlock)changeBlock {
self = [super init];
if (!self)
return nil;
self.subject = subject;
self.keyPath = keyPath;
self.changeBlock = changeBlock;
[subject addObserver:self
forKeyPath:_keyPath
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
context:nil];
return self;
}
- (void)dealloc {
[_subject removeObserver:self forKeyPath:_keyPath];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:_keyPath]) {
id newValue = [change valueForKey:NSKeyValueChangeNewKey];
_changeBlock(newValue);
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment