title: iOS - How to remove observer from singleton NSObject for KVO?
body: <p>I have a shared singleton class of NSObject that I have some operation queues running in. I get a crash on this:</p>
  
  <pre><code>[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  </code></pre>
  
  <p>It seems that I need to use 'removeObserver:' to prevent this from happening, but how do I properly do that on a shared object?</p>
  
  <p><strong>CODE:</strong></p>
  
  <pre><code>-(void)synchronizeToDevice{
      queue = [NSOperationQueue new];
      queue.name = @"SynchronizeToDeviceQueue";
      //Sync Active User
      NSInvocationOperation *operationUser = [[NSInvocationOperation alloc] initWithTarget:self
                                                                                  selector:@selector(downloadUserData:)
                                                                                object:[self activeUserID]];
  
      [queue addOperation:operationUser];
  
      //Sync Video Data
      NSInvocationOperation *operationVideos = [[NSInvocationOperation alloc] initWithTarget:self
                                                                              selector:@selector(downloadVideoData)
                                                                                object:nil];
      [queue addOperation:operationVideos];
  
  
      [queue addObserver:self forKeyPath:@"operations" options:0 context:NULL];
  }
  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
  {
      if (object == queue &amp;&amp; [keyPath isEqualToString:@"operations"]) {
          //Synchronization Queue
          if ([queue.name isEqualToString:@"SynchronizeToDeviceQueue"] &amp;&amp; [queue.operations count] == 0) {
              //Queue Completed
              //Notify View Synchronization Completed
              [self performSelectorOnMainThread:@selector(postNotificationDidFinishSynchronizationToDevice) withObject:nil waitUntilDone:NO];
          }
          //Video Download Queue
          if ([queue.name isEqualToString:@"VideoFileDownloadQueue"] &amp;&amp; [queue.operations count] == 0) {
              //Notify View Video File Download Completed
              [self performSelectorOnMainThread:@selector(postNotificationDidFinishDownloadingVideo) withObject:nil waitUntilDone:NO];
          }
          //Active User Sync Queue
          if ([queue.name isEqualToString:@"SynchronizeActiveUserToDeviceQueue"] &amp;&amp; [queue.operations count] == 0) {
              //Queue Completed
              //Notify View Synchronization Completed
              [self performSelectorOnMainThread:@selector(postNotificationDidFinishActiveUserSynchronizationToDevice) withObject:nil waitUntilDone:NO];
          }
      }
      else {
          [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
      }
  }
  </code></pre>
  
  <p><strong>CRASH LOG:</strong></p>
  
  <pre><code>2013-03-14 21:48:42.167 COMPANY[1946:1103] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '&lt;DataManager: 0x1c54a420&gt;: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
  Key path: operations
  Observed object: &lt;NSOperationQueue: 0x1c5d3360&gt;{name = 'SynchronizeActiveUserToDeviceQueue'}
  Change: {
      kind = 1;
  }
  Context: 0x0'
  *** First throw call stack:
  (0x336262a3 0x3b4b197f 0x336261c5 0x33f1a56d 0x21bd1 0x33eb46b9 0x33eb4313 0x33eb3a25 0x33eb3817 0x33f2b689 0x3b8ccb97 0x3b8cf139 0x3b8cd91d 0x3b8cdac1 0x3b8fda11 0x3b8fd8a4)
  libc++abi.dylib: terminate called throwing an exception
  </code></pre>