RACDelegateProxy.m 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //
  2. // RACDelegateProxy.m
  3. // ReactiveObjC
  4. //
  5. // Created by Cody Krieger on 5/19/12.
  6. // Copyright (c) 2012 GitHub, Inc. All rights reserved.
  7. //
  8. #import "RACDelegateProxy.h"
  9. #import "NSObject+RACSelectorSignal.h"
  10. #import <objc/runtime.h>
  11. @interface RACDelegateProxy () {
  12. // Declared as an ivar to avoid method naming conflicts.
  13. Protocol *_protocol;
  14. }
  15. @end
  16. @implementation RACDelegateProxy
  17. #pragma mark Lifecycle
  18. - (instancetype)initWithProtocol:(Protocol *)protocol {
  19. NSCParameterAssert(protocol != NULL);
  20. self = [super init];
  21. class_addProtocol(self.class, protocol);
  22. _protocol = protocol;
  23. return self;
  24. }
  25. #pragma mark API
  26. - (RACSignal *)signalForSelector:(SEL)selector {
  27. return [self rac_signalForSelector:selector fromProtocol:_protocol];
  28. }
  29. #pragma mark NSObject
  30. - (BOOL)isProxy {
  31. return YES;
  32. }
  33. - (void)forwardInvocation:(NSInvocation *)invocation {
  34. [invocation invokeWithTarget:self.rac_proxiedDelegate];
  35. }
  36. - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
  37. // Look for the selector as an optional instance method.
  38. struct objc_method_description methodDescription = protocol_getMethodDescription(_protocol, selector, NO, YES);
  39. if (methodDescription.name == NULL) {
  40. // Then fall back to looking for a required instance
  41. // method.
  42. methodDescription = protocol_getMethodDescription(_protocol, selector, YES, YES);
  43. if (methodDescription.name == NULL) return [super methodSignatureForSelector:selector];
  44. }
  45. return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
  46. }
  47. - (BOOL)respondsToSelector:(SEL)selector {
  48. // Add the delegate to the autorelease pool, so it doesn't get deallocated
  49. // between this method call and -forwardInvocation:.
  50. __autoreleasing id delegate = self.rac_proxiedDelegate;
  51. if ([delegate respondsToSelector:selector]) return YES;
  52. return [super respondsToSelector:selector];
  53. }
  54. @end