Advertisement
sophtwhere

NSObject+KVO_Blocks.m

Nov 5th, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. //  NSObject+KVO_Blocks.m
  3. //
  4. //  Created by Jonathan Annett on 1/11/13.
  5. //  Copyright (c) 2013 Sophtwhere. All rights reserved.
  6. //
  7.  
  8. #import "NSObject+KVO_Blocks.h"
  9. #import "NSObject+arcAgnostics.h"
  10. #import <objc/runtime.h>
  11.  
  12. @implementation NSObject (KVOBlocks)
  13.  
  14. - (void)addObserverForKeyPath:(NSString *)keyPath
  15.                       options:(NSKeyValueObservingOptions)options
  16.                       context:(void *)context
  17.                     withBlock:(KVOBlock)block
  18. {
  19.     CFTypeRef key = CFBridgingRetain(keyPath);
  20.     NSMutableArray *observers =   (__bridge NSMutableArray*) objc_getAssociatedObject(self, key);
  21.    
  22.     if (observers) {
  23.         [observers addObject:Block_copy(block)];
  24.     } else {
  25.         observers = [[NSMutableArray alloc] initWithObjects:Block_copy(block), nil];
  26.         objc_setAssociatedObject(self, key, (__bridge NSMutableArray*) observers, OBJC_ASSOCIATION_ASSIGN);
  27.     }
  28.     [self addObserver:self forKeyPath:keyPath options:options context:context];
  29.     CFBridgingRelease(key);
  30. }
  31.  
  32. - (void)observeValueForKeyPath:(NSString *)keyPath
  33.                       ofObject:(id)object
  34.                         change:(NSDictionary *)change
  35.                        context:(void *)context
  36. {
  37.    
  38.     CFTypeRef key = CFBridgingRetain(keyPath);
  39.     NSMutableArray *observers =   (__bridge NSMutableArray*) objc_getAssociatedObject(self, key);
  40.     CFBridgingRelease(key);
  41.    
  42.     if (observers) {
  43.         NSInteger ix = 0;
  44.         while (ix < observers.count) {
  45.             KVOBlock locateBlock =  [observers objectAtIndex:ix];
  46.             locateBlock(keyPath,[(id)self objectForKey:keyPath],change,context);
  47.             ix ++;
  48.         }
  49.     }
  50. }
  51.  
  52. - (void)removeBlock:(KVOBlock)block observerForKeyPath:(NSString *)keyPath
  53. {
  54.     CFTypeRef key = CFBridgingRetain(keyPath);
  55.     NSMutableArray *observers =   (__bridge NSMutableArray*) objc_getAssociatedObject(self, key);
  56.     CFBridgingRelease(key);
  57.     if (observers) {
  58.         if (block) {
  59.             NSInteger ix = 0;
  60.             while (ix < observers.count) {
  61.                 KVOBlock locateBlock =  [observers objectAtIndex:ix];
  62.                 if (locateBlock==block) {
  63.                     Block_release(locateBlock);
  64.                     [observers removeObjectAtIndex:ix];
  65.                 } else {
  66.                     ix ++;
  67.                 }
  68.             }
  69.            
  70.         } else {
  71.            
  72.             while (observers.count>0) {
  73.                 KVOBlock locateBlock = observers.lastObject;
  74.                 Block_release(locateBlock);
  75.                 [observers removeLastObject];
  76.             }
  77.         }
  78.        
  79.         if (observers.count==0) {
  80.             objc_setAssociatedObject(self,key, nil, OBJC_ASSOCIATION_COPY);
  81.             [self removeObserver:self forKeyPath:keyPath];
  82.             [observers release];
  83.         }
  84.     } else {
  85.         [self removeObserver:self forKeyPath:keyPath];
  86.     }
  87.     CFBridgingRelease(key);
  88.    
  89. }
  90.  
  91. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement