Created
September 8, 2010 16:30
-
-
Save nevyn/570377 to your computer and use it in GitHub Desktop.
Bindings for iOS
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
#import <Foundation/Foundation.h> | |
@interface NSObject (SPBindings) | |
-(void)sp_bind:(NSString*)binding toObject:(id)observable withKeyPath:(NSString*)observableKeyPath; | |
-(void)sp_unbind:(NSString*)binding; | |
@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
#import "SPBindings.h" | |
@interface SPBinding : NSObject | |
{ | |
id object; | |
id observable; | |
NSString *objectKeyPath; | |
NSString *observableKeyPath; | |
} | |
@property (nonatomic, assign) id object; | |
@property (nonatomic, assign) id observable; | |
@property (nonatomic, copy) NSString *objectKeyPath; | |
@property (nonatomic, copy) NSString *observableKeyPath; | |
@end | |
@implementation SPBinding | |
@synthesize object, observable, objectKeyPath, observableKeyPath; | |
+binding; | |
{ | |
return [[[SPBinding alloc] init] autorelease]; | |
} | |
-(void)dealloc; | |
{ | |
self.object = self.observable = self.objectKeyPath = self.observableKeyPath; | |
[super dealloc]; | |
} | |
-(NSString*)ident; | |
{ | |
return [NSString stringWithFormat:@"%x.%@", object, objectKeyPath]; | |
} | |
@end | |
@class SPBindings; | |
static SPBindings *singleton = nil; | |
@interface SPBindings : NSObject { | |
NSMutableDictionary *bindings; | |
} | |
-(void)bind:(id)obj from:(NSString*)binding toObject:(id)observable withKeyPath:(NSString*)observableKeyPath; | |
-(void)unbind:(id)obj from:(NSString*)binding; | |
@end | |
@implementation SPBindings | |
+sharedBindings; | |
{ | |
if(!singleton) singleton = [SPBindings new]; | |
return singleton; | |
} | |
-init; | |
{ | |
bindings = [NSMutableDictionary new]; | |
return self; | |
} | |
-(void)dealloc; | |
{ | |
for (SPBinding *binding in bindings) | |
[self unbind:binding.object from:binding.objectKeyPath]; | |
[bindings release]; | |
[super dealloc]; | |
} | |
-(void)bind:(id)obj from:(NSString*)objKeyPath toObject:(id)observable withKeyPath:(NSString*)observableKeyPath; | |
{ | |
SPBinding *binding = [SPBinding binding]; | |
binding.object = obj; | |
binding.observable = observable; | |
binding.objectKeyPath = objKeyPath; | |
binding.observableKeyPath = observableKeyPath; | |
SPBinding *oldBinding = [bindings objectForKey:binding.ident]; | |
if(oldBinding) [self unbind:oldBinding.object from:oldBinding.objectKeyPath]; | |
[bindings setObject:binding forKey:binding.ident]; | |
[obj addObserver:self forKeyPath:objKeyPath options:NSKeyValueObservingOptionNew context:binding]; | |
[observable addObserver:self forKeyPath:observableKeyPath options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:binding]; | |
} | |
-(void)unbind:(id)obj from:(NSString*)objKeyPath; | |
{ | |
SPBinding *templateBinding = [SPBinding binding]; | |
templateBinding.object = obj; | |
templateBinding.objectKeyPath = objKeyPath; | |
SPBinding *binding = [[[bindings objectForKey:templateBinding.ident] retain] autorelease]; | |
[bindings removeObjectForKey:templateBinding.ident]; | |
[binding.object removeObserver:self forKeyPath:binding.objectKeyPath]; | |
[binding.observable removeObserver:self forKeyPath:binding.observableKeyPath]; | |
} | |
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; | |
{ | |
SPBinding *binding = (id)context; | |
// Update the object that this is *not* a KVO for (to mirror the value) | |
id o; NSString *path; | |
if(object == binding.object) { | |
o = binding.observable; | |
path = binding.observableKeyPath; | |
} else { | |
o = binding.object; | |
path = binding.objectKeyPath; | |
} | |
[o removeObserver:self forKeyPath:path]; | |
[o setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:path]; | |
[o addObserver:self forKeyPath:path options:NSKeyValueObservingOptionNew context:binding]; | |
} | |
@end | |
@implementation NSObject (SPBindings) | |
-(void)sp_bind:(NSString*)binding toObject:(id)observable withKeyPath:(NSString*)observableKeyPath; | |
{ | |
[[SPBindings sharedBindings] bind:self from:binding toObject:observable withKeyPath:observableKeyPath]; | |
} | |
-(void)sp_unbind:(NSString*)binding; | |
{ | |
[[SPBindings sharedBindings] unbind:self from:binding]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment