Permalink
Browse files

Refactor to make roles clearer

  • Loading branch information...
1 parent a685be3 commit 8549777946603e9a0945e208ed3a6e7f7786c3d8 Hamish Allan committed Oct 3, 2011
View
@@ -0,0 +1,23 @@
+//
+// DGKVOBlocksObserver.h
+// DGKVOBlocks
+//
+// Created by Hamish Allan on 03/10/2011.
+// Copyright (c) 2011 No Thirst Software. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+extern NSString *const DGKVOBlocksObservationContext;
+
+typedef void (^DGKVOObserverBlock)(NSDictionary *change);
+
+@interface DGKVOBlocksObserver : NSObject
+
+@property (readonly) NSOperationQueue *queue;
+@property (readonly) DGKVOObserverBlock block;
+
+- (id)initWithQueue:(NSOperationQueue *)queue block:(DGKVOObserverBlock)block;
+
+@end
+
View
@@ -0,0 +1,70 @@
+//
+// DGKVOBlocksObserver.m
+// DGKVOBlocks
+//
+// Created by Hamish Allan on 03/10/2011.
+// Copyright (c) 2011 No Thirst Software. All rights reserved.
+//
+
+#import "DGKVOBlocksObserver.h"
+
+NSString *const DGKVOBlocksObservationContext = @"DGKVOBlocksObservationContext";
+
+#if __has_feature(objc_arc)
+#define DGKVOBlocksObserversAssociatedObjectsKey ((__bridge const void *)DGKVOBlocksObserversAssociatedObjectsKey)
+#endif
+
+@implementation DGKVOBlocksObserver
+
+@synthesize queue = _queue, block = _block;
+
+#if !__has_feature(objc_arc)
+- (void)dealloc
+{
+ [_queue release];
+ [_block release];
+
+ [super dealloc];
+}
+#endif
+
+- (id)initWithQueue:(NSOperationQueue *)queue block:(DGKVOObserverBlock)block
+{
+ self = [super init];
+
+ if (self) {
+#if __has_feature(objc_arc)
+ _queue = queue;
+#else
+ _queue = [queue retain];
+#endif
+ _block = [block copy];
+ }
+
+ return self;
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if (context == DGKVOBlocksObservationContext) {
+
+ if (self.queue) {
+ NSDictionary *copiedChange = [change copy];
+
+ [self.queue addOperationWithBlock: ^ {
+ self.block(copiedChange);
+ }];
+
+#if !__has_feature(objc_arc)
+ [copiedChange release];
+#endif
+ } else {
+ self.block(change);
+ }
+
+ } else {
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ }
+}
+
+@end
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 1CF926B9143A3AAA006BD46C /* DGKVOBlocksObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CF926B8143A3AAA006BD46C /* DGKVOBlocksObserver.m */; };
308679161439E8EF004A54A0 /* NSObject+DGKVOBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 308679151439E8EF004A54A0 /* NSObject+DGKVOBlocks.m */; };
30C994521438716C00966C25 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30C994511438716C00966C25 /* Cocoa.framework */; };
30C9945C1438716C00966C25 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 30C9945A1438716C00966C25 /* InfoPlist.strings */; };
@@ -17,6 +18,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 1CF926B7143A3AAA006BD46C /* DGKVOBlocksObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DGKVOBlocksObserver.h; path = ../../DGKVOBlocksObserver.h; sourceTree = "<group>"; };
+ 1CF926B8143A3AAA006BD46C /* DGKVOBlocksObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DGKVOBlocksObserver.m; path = ../../DGKVOBlocksObserver.m; sourceTree = "<group>"; };
308679141439E8EF004A54A0 /* NSObject+DGKVOBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSObject+DGKVOBlocks.h"; path = "../../NSObject+DGKVOBlocks.h"; sourceTree = "<group>"; };
308679151439E8EF004A54A0 /* NSObject+DGKVOBlocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSObject+DGKVOBlocks.m"; path = "../../NSObject+DGKVOBlocks.m"; sourceTree = "<group>"; };
30C9944D1438716C00966C25 /* DGKVOBlocks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DGKVOBlocks.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -96,6 +99,8 @@
30C994571438716C00966C25 /* DGKVOBlocks */ = {
isa = PBXGroup;
children = (
+ 1CF926B7143A3AAA006BD46C /* DGKVOBlocksObserver.h */,
+ 1CF926B8143A3AAA006BD46C /* DGKVOBlocksObserver.m */,
308679141439E8EF004A54A0 /* NSObject+DGKVOBlocks.h */,
308679151439E8EF004A54A0 /* NSObject+DGKVOBlocks.m */,
308679131439E8D5004A54A0 /* Example */,
@@ -182,6 +187,7 @@
30C9945E1438716C00966C25 /* main.m in Sources */,
30C994651438716C00966C25 /* DGAppDelegate.m in Sources */,
308679161439E8EF004A54A0 /* NSObject+DGKVOBlocks.m in Sources */,
+ 1CF926B9143A3AAA006BD46C /* DGKVOBlocksObserver.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -32,7 +32,7 @@ - (id)init
}
- (void)dealloc {
- [self dgkvo_removeObserverWithIdentifier:numberObserver];
+ [self dgkvo_removeObserver:numberObserver];
}
@@ -47,7 +47,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
self.string = @"TWO";
self.string = @"THREE";
- [self dgkvo_removeObserverWithIdentifier:stringObserver];
+ [self dgkvo_removeObserver:stringObserver];
self.string = @"This should not appear.";
View
@@ -26,11 +26,11 @@
#import <Foundation/Foundation.h>
-typedef void (^DGKVOObserverBlock)(NSDictionary *change);
+#import "DGKVOBlocksObserver.h"
@interface NSObject (DGKVOBlocks)
- (id)dgkvo_addObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options queue:(NSOperationQueue *)queue usingBlock:(DGKVOObserverBlock)block;
-- (void)dgkvo_removeObserverWithIdentifier:(id)identifier;
+- (void)dgkvo_removeObserver:(id)observer;
@end
View
@@ -24,96 +24,35 @@
//*******************************************************************************
-#import "NSObject+DGKVOBlocks.h"
-
#import <objc/runtime.h>
-//***************************************************************************
-
-NSString *DGKVOBlocksObservationContext = @"DGKVOBlocksObservationContext";
-
-NSString *const DGKVOBlocksObserversAssociatedObjectsKey = @"DGKVOBlocksObserversAssociatedObjectsKey";
-
-#if __has_feature(objc_arc)
-#define DGKVOBlocksObserversAssociatedObjectsKey (__bridge const void *)DGKVOBlocksObserversAssociatedObjectsKey
-#endif
+#import "NSObject+DGKVOBlocks.h"
//***************************************************************************
-@interface DGKVOBlocksObserver : NSObject
+static NSString *const DGKVOBlocksBlockObserversKey = @"DGKVOBlocksBlockObserversKey";
+static NSString *const DGKVOBlocksKeyPathKey = @"DGKVOBlocksKeyPathKey";
-@property (copy) DGKVOObserverBlock block;
-@property (copy) NSString *keyPath;
-@property (retain) NSOperationQueue *queue;
-
-@end
+@interface NSObject (DGKVOBlocksProperties)
-@implementation DGKVOBlocksObserver
-
-@synthesize block = _block;
-@synthesize keyPath = _keyPath;
-@synthesize queue = _queue;
-
-#if !__has_feature(objc_arc)
-- (void)dealloc
-{
- [_keyPath release];
- [_queue release];
- [_block release];
-
- [super dealloc];
-}
-#endif
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
- if (context == &DGKVOBlocksObservationContext) {
- if (self.queue == nil) {
- self.block(change);
- return;
- }
-
- NSDictionary *copiedChange = [change copy];
- [self.queue addOperationWithBlock: ^ {
- self.block(copiedChange);
- }];
-
-#if !__has_feature(objc_arc)
- [copiedChange release];
-#endif
-
- } else {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
-}
-
-@end
-
-//***************************************************************************
-
-@interface NSObject (DGKVOBlocksProperties)
-
-@property (readonly) NSMutableArray *dgkvo_blockObservers;
+@property (readonly) NSMutableSet *dgkvo_blockObservers;
@end
@implementation NSObject (DGKVOBlocksProperties)
-- (NSMutableArray *)dgkvo_blockObservers
+- (NSMutableSet *)dgkvo_blockObservers
{
@synchronized (self) {
- NSMutableArray *setDict = objc_getAssociatedObject(self, DGKVOBlocksObserversAssociatedObjectsKey);
-
- if (setDict == nil) {
- NSMutableArray *newSetDict = [NSMutableArray array];
-
- objc_setAssociatedObject(self, DGKVOBlocksObserversAssociatedObjectsKey, newSetDict, OBJC_ASSOCIATION_RETAIN);
-
- return newSetDict;
+ NSMutableSet *set = objc_getAssociatedObject(self, DGKVOBlocksBlockObserversKey);
+
+ if (set == nil) {
+ set = [NSMutableArray array];
+ objc_setAssociatedObject(self, DGKVOBlocksBlockObserversKey, set, OBJC_ASSOCIATION_RETAIN);
}
- return setDict;
+ return set;
}
}
@@ -127,30 +66,30 @@ - (id)dgkvo_addObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservi
{
NSAssert(block != nil, @"You cannot add a block observer without a block.");
- DGKVOBlocksObserver *newBlocksObserver = [[DGKVOBlocksObserver alloc] init];
- newBlocksObserver.block = block;
- newBlocksObserver.keyPath = keyPath;
- newBlocksObserver.queue = queue;
-
- [self addObserver:newBlocksObserver forKeyPath:keyPath options:options context:&DGKVOBlocksObservationContext];
+ DGKVOBlocksObserver *observer = [[DGKVOBlocksObserver alloc] initWithQueue:queue block:block];
+
+ objc_setAssociatedObject(observer, DGKVOBlocksKeyPathKey, keyPath, OBJC_ASSOCIATION_COPY);
+
+ [self addObserver:observer forKeyPath:keyPath options:options context:DGKVOBlocksObservationContext];
@synchronized (self.dgkvo_blockObservers) {
- [self.dgkvo_blockObservers addObject:newBlocksObserver];
+ [self.dgkvo_blockObservers addObject:observer];
}
#if !__has_feature(objc_arc)
- [newBlocksObserver release];
+ [observer release];
#endif
- return newBlocksObserver;
+ return observer;
}
-- (void)dgkvo_removeObserverWithIdentifier:(id)identifier
+- (void)dgkvo_removeObserver:(id)observer
{
- [self removeObserver:identifier forKeyPath:[identifier keyPath]];
+ NSString *keyPath = objc_getAssociatedObject(observer, DGKVOBlocksKeyPathKey);
+ [self removeObserver:observer forKeyPath:keyPath];
@synchronized (self.dgkvo_blockObservers) {
- [self.dgkvo_blockObservers removeObjectIdenticalTo:identifier];
+ [self.dgkvo_blockObservers removeObject:observer];
}
}

0 comments on commit 8549777

Please sign in to comment.