RACKVOProxy.m 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //
  2. // RACKVOProxy.m
  3. // ReactiveCocoa
  4. //
  5. // Created by Richard Speyer on 4/10/14.
  6. // Copyright (c) 2014 GitHub, Inc. All rights reserved.
  7. //
  8. #import "RACKVOProxy.h"
  9. @interface RACKVOProxy()
  10. @property (strong, nonatomic, readonly) NSMapTable *trampolines;
  11. @property (strong, nonatomic, readonly) dispatch_queue_t queue;
  12. @end
  13. @implementation RACKVOProxy
  14. + (instancetype)sharedProxy {
  15. static RACKVOProxy *proxy;
  16. static dispatch_once_t onceToken;
  17. dispatch_once(&onceToken, ^{
  18. proxy = [[self alloc] init];
  19. });
  20. return proxy;
  21. }
  22. - (instancetype)init {
  23. self = [super init];
  24. if (self == nil) return nil;
  25. _queue = dispatch_queue_create("org.reactivecocoa.ReactiveCocoa.RACKVOProxy", DISPATCH_QUEUE_SERIAL);
  26. _trampolines = [NSMapTable strongToWeakObjectsMapTable];
  27. return self;
  28. }
  29. - (void)addObserver:(__weak NSObject *)observer forContext:(void *)context {
  30. NSValue *valueContext = [NSValue valueWithPointer:context];
  31. dispatch_sync(self.queue, ^{
  32. [self.trampolines setObject:observer forKey:valueContext];
  33. });
  34. }
  35. - (void)removeObserver:(NSObject *)observer forContext:(void *)context {
  36. NSValue *valueContext = [NSValue valueWithPointer:context];
  37. dispatch_sync(self.queue, ^{
  38. [self.trampolines removeObjectForKey:valueContext];
  39. });
  40. }
  41. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  42. NSValue *valueContext = [NSValue valueWithPointer:context];
  43. __block NSObject *trueObserver;
  44. dispatch_sync(self.queue, ^{
  45. trueObserver = [self.trampolines objectForKey:valueContext];
  46. });
  47. if (trueObserver != nil) {
  48. [trueObserver observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  49. }
  50. }
  51. @end