/core/externals/google-toolbox-for-mac/Foundation/GTMLightweightProxy.m

http://macfuse.googlecode.com/ · Objective C · 108 lines · 59 code · 14 blank · 35 comment · 10 complexity · 020c979b8d50a753829c137de6eb8916 MD5 · raw file

  1. //
  2. // GTMLightweightProxy.m
  3. //
  4. // Copyright 2006-2008 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations under
  16. // the License.
  17. //
  18. #import "GTMLightweightProxy.h"
  19. #import "GTMDefines.h"
  20. @implementation GTMLightweightProxy
  21. - (id)initWithRepresentedObject:(id)object {
  22. // it's weak, we don't retain
  23. representedObject_ = object;
  24. return self;
  25. }
  26. - (id)init {
  27. return [self initWithRepresentedObject:nil];
  28. }
  29. - (void)dealloc {
  30. // it's weak, we don't release
  31. representedObject_ = nil;
  32. [super dealloc];
  33. }
  34. - (id)representedObject {
  35. // Use a local variable to avoid a bogus compiler warning.
  36. id repObject = nil;
  37. @synchronized(self) {
  38. // Even though we don't retain this object, we hang it on the lifetime
  39. // of the calling threads pool so it's lifetime is safe for at least that
  40. // long.
  41. repObject = [representedObject_ retain];
  42. }
  43. return [repObject autorelease];
  44. }
  45. - (void)setRepresentedObject:(id)object {
  46. @synchronized(self) {
  47. representedObject_ = object;
  48. }
  49. }
  50. // Passes any unhandled method to the represented object if it responds to that
  51. // method.
  52. - (void)forwardInvocation:(NSInvocation*)invocation {
  53. id target = [self representedObject];
  54. // Silently discard all messages when there's no represented object
  55. if (!target)
  56. return;
  57. SEL aSelector = [invocation selector];
  58. if ([target respondsToSelector:aSelector])
  59. [invocation invokeWithTarget:target];
  60. }
  61. // Gets the represented object's method signature for |selector|; necessary for
  62. // forwardInvocation.
  63. - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
  64. id target = [self representedObject];
  65. if (target) {
  66. return [target methodSignatureForSelector:selector];
  67. } else {
  68. // Apple's underlying forwarding code crashes if we return nil here.
  69. // Since we are not going to use the invocation being constructed
  70. // if there's no representedObject, a random valid NSMethodSignature is fine.
  71. return [NSObject methodSignatureForSelector:@selector(alloc)];
  72. }
  73. }
  74. // Prevents exceptions from unknown selectors if there is no represented
  75. // object, and makes the exception come from the right place if there is one.
  76. - (void)doesNotRecognizeSelector:(SEL)selector {
  77. id target = [self representedObject];
  78. if (target)
  79. [target doesNotRecognizeSelector:selector];
  80. }
  81. // Checks the represented object's selectors to allow clients of the proxy to
  82. // do respondsToSelector: tests.
  83. - (BOOL)respondsToSelector:(SEL)selector {
  84. if ([super respondsToSelector:selector] ||
  85. selector == @selector(initWithRepresentedObject:) ||
  86. selector == @selector(representedObject) ||
  87. selector == @selector(setRepresentedObject:))
  88. {
  89. return YES;
  90. }
  91. id target = [self representedObject];
  92. return target && [target respondsToSelector:selector];
  93. }
  94. @end