Skip to content

Instantly share code, notes, and snippets.

@nevyn
Created September 8, 2010 16:30
Show Gist options
  • Save nevyn/570377 to your computer and use it in GitHub Desktop.
Save nevyn/570377 to your computer and use it in GitHub Desktop.
Bindings for iOS
#import <Foundation/Foundation.h>
@interface NSObject (SPBindings)
-(void)sp_bind:(NSString*)binding toObject:(id)observable withKeyPath:(NSString*)observableKeyPath;
-(void)sp_unbind:(NSString*)binding;
@end
#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