public CFNotificationObserverToken AddObserver(string name, INativeObject objectToObserve, Action <string, NSDictionary> notificationHandler,
                                                       CFNotificationSuspensionBehavior suspensionBehavior = CFNotificationSuspensionBehavior.DeliverImmediately)
        {
            if (darwinnc != null && darwinnc.Handle == Handle)
            {
                if (name == null)
                {
                    throw new ArgumentNullException("name", "When using the Darwin Notification Center, the value passed must not be null");
                }
            }

            var strHandle = name == null ? IntPtr.Zero : NSString.CreateNative(name);

            name = name ?? NullNotificationName;
            var token = new CFNotificationObserverToken()
            {
                stringName     = name,
                centerHandle   = handle,
                nameHandle     = strHandle,
                observedObject = objectToObserve == null ? IntPtr.Zero : objectToObserve.Handle,
                listener       = notificationHandler
            };

            //
            // To allow callbacks to add observers, we duplicate the list of listeners on AddObserver
            // We do the duplication on AddObserver, instead of making a copy on the notification
            // callback, as we expect the notification callback to be a more common operation
            // than the AddObserver operation
            //
            List <CFNotificationObserverToken> listenersForName;

            lock (listeners){
                if (!listeners.TryGetValue(name, out listenersForName))
                {
                    listenersForName = new List <CFNotificationObserverToken> (1);
                    CFNotificationCenterAddObserver(center: handle,
                                                    observer: handle,
                                                    callback: NotificationCallback,
                                                    name: strHandle,
                                                    obj: token.observedObject,
                                                    suspensionBehavior: (IntPtr)suspensionBehavior);
                }
                else
                {
                    listenersForName = new List <CFNotificationObserverToken> (listenersForName);
                }
                listenersForName.Add(token);
                listeners [name] = listenersForName;
            }
            return(token);
        }
 public void RemoveObserver(CFNotificationObserverToken token)
 {
     if (token == null)
     {
         throw new ArgumentNullException("token");
     }
     if (token.nameHandle == IntPtr.Zero && token.stringName != NullNotificationName)
     {
         throw new ObjectDisposedException("token");
     }
     if (token.centerHandle != handle)
     {
         throw new ArgumentException("token", "This token belongs to a different notification center");
     }
     lock (listeners){
         var list = listeners [token.stringName];
         List <CFNotificationObserverToken> newList = null;
         foreach (var e in list)
         {
             if (e == token)
             {
                 continue;
             }
             if (newList == null)
             {
                 newList = new List <CFNotificationObserverToken> ();
             }
             newList.Add(e);
         }
         if (newList != null)
         {
             listeners [token.stringName] = newList;
             return;
         }
         else
         {
             listeners.Remove(token.stringName);
         }
     }
     CFNotificationCenterRemoveObserver(handle, this.Handle, name: token.nameHandle, obj: token.observedObject);
     NSString.ReleaseNative(token.nameHandle);
     token.nameHandle = IntPtr.Zero;
 }