KVUtils.m
author Jens Alfke <jens@mooseyard.com>
Sun Apr 06 19:13:27 2008 -0700 (2008-04-06)
changeset 3 8fad19466c59
parent 0 d84d25d6cdbb
child 11 e5976864dfe9
permissions -rw-r--r--
Miscellaneous improvements.
     1 //
     2 //  KVUtils.m
     3 //  MYUtilities
     4 //
     5 //  Created by Jens Alfke on 2/25/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "KVUtils.h"
    10 
    11 
    12 @implementation Observance
    13 
    14 - (id) initWithTarget: (id)target 
    15                action: (SEL)action
    16              observed: (id)observed
    17               keyPath: (NSString*)keyPath 
    18               options: (NSKeyValueObservingOptions)options
    19 {
    20     self = [super init];
    21     if (self != nil) {
    22         _target = target;
    23         _action = action;
    24         _observed = observed;
    25         _keyPath = [keyPath copy];
    26         _options = options;
    27         
    28         options &= ~(MYKeyValueObservingOptionOnce | MYKeyValueObservingOptionDelayed);
    29         
    30         [_observed addObserver: self forKeyPath: _keyPath options: options context: _action];
    31     }
    32     return self;
    33 }
    34 
    35 - (void) dealloc
    36 {
    37     [_observed removeObserver: self forKeyPath: _keyPath];
    38     [_keyPath release];
    39     [super dealloc];
    40 }
    41 
    42 
    43 @synthesize observed=_observed, keyPath=_keyPath;
    44 
    45 
    46 - (void) stopObserving
    47 {
    48     [_observed removeObserver: self forKeyPath: _keyPath];
    49     _observed = nil;
    50     _target = nil;
    51     _action = NULL;
    52 }
    53 
    54 
    55 - (void) _callTargetWithChange: (NSDictionary*)change
    56 {
    57     @try{
    58         [_target performSelector: _action withObject: _observed withObject: change];
    59     }@catch( NSException *x ) {
    60         Warn(@"Uncaught exception in -[%@<%p> %s] while observing change of key-path %@ in %@<%p>: %@",
    61              _target,_target, _action, _keyPath, _observed,_observed, x);
    62         [NSApp reportException: x];
    63     }
    64 }
    65 
    66 
    67 - (void)observeValueForKeyPath:(NSString *)keyPath 
    68                       ofObject:(id)object 
    69                         change:(NSDictionary *)change 
    70                        context:(void *)context
    71 {
    72     if( object == _observed ) {
    73         if( _options & MYKeyValueObservingOptionDelayed )
    74             [self performSelector: @selector(_callTargetWithChange:) withObject: change
    75                        afterDelay: 0.0];
    76         else
    77             [self _callTargetWithChange: change];
    78         if( _options & MYKeyValueObservingOptionOnce )
    79             [self stopObserving];
    80     }
    81 }
    82 
    83 
    84 @end
    85 
    86 
    87 
    88 
    89 @implementation Observer
    90 
    91 
    92 - (id) init
    93 {
    94     return [self initWithTarget: self];
    95 }
    96 
    97 
    98 
    99 - (id) initWithTarget: (id)target
   100 {
   101     Assert(target);
   102     self = [super init];
   103     if (self != nil) {
   104         _target = target;
   105         _observances = [[NSMutableArray alloc] init];
   106     }
   107     return self;
   108 }
   109 
   110 
   111 - (void) dealloc
   112 {
   113     [self stopObserving];
   114     [_observances release];
   115     [super dealloc];
   116 }
   117 
   118 
   119 @synthesize target=_target;
   120 
   121 
   122 - (void) observe: (id)observed 
   123          keyPath: (NSString*)keyPath 
   124          options: (NSKeyValueObservingOptions)options
   125           action: (SEL)action
   126 {
   127     Observance *o = [[Observance alloc] initWithTarget: _target
   128                                                 action: action
   129                                               observed: observed
   130                                                keyPath: keyPath
   131                                                options: options];
   132     [_observances addObject: o];
   133     [o release];
   134 }
   135 
   136 
   137 - (void) observe: (id)observed 
   138          keyPath: (NSString*)keyPath 
   139           action: (SEL)action
   140 {
   141     [self observe: observed keyPath: keyPath options: 0 action: action];
   142 }
   143 
   144 
   145 - (void) stopObserving
   146 {
   147     [_observances makeObjectsPerformSelector: @selector(stopObserving)];
   148     [_observances removeAllObjects];
   149 }
   150 
   151 
   152 - (void) stopObserving: (id)observed
   153 {
   154     [self stopObserving: observed keyPath: nil];
   155 }
   156 
   157 
   158 - (void) stopObserving: (id)observed keyPath: (NSString*)keyPath
   159 {
   160     // observed or keyPath may be nil
   161     for( int i=_observances.count-1; i>=0; i-- ) {
   162         Observance *o = [_observances objectAtIndex: i];
   163         if( (observed==nil || observed==o.observed) && (keyPath==nil || [keyPath isEqual: o.keyPath]) ) {
   164             [o stopObserving];
   165             [_observances removeObjectAtIndex: i];
   166         }
   167     }
   168 }
   169 
   170 @end