ManagedObjectWrapper.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #if defined(__OBJC__) && defined(__cplusplus)
  9. #if TARGET_OS_MAC && TARGET_OS_IPHONE
  10. #include <memory>
  11. #import <Foundation/Foundation.h>
  12. @interface RCTInternalGenericWeakWrapper : NSObject
  13. @property (nonatomic, weak) id object;
  14. @end
  15. namespace facebook {
  16. namespace react {
  17. /*
  18. * `wrapManagedObject` and `unwrapManagedObject` are wrapper functions that
  19. * convert ARC-managed objects into `std::shared_ptr<void>` and vice-versa. It's
  20. * a very useful mechanism when we need to pass Objective-C objects through pure
  21. * C++ code, pass blocks into C++ lambdas, and so on.
  22. *
  23. * The idea behind this mechanism is quite simple but tricky: When we
  24. * instantiate a C++ shared pointer for a managed object, we practically call
  25. * `CFRetain` for it once and then we represent this single retaining operation
  26. * as a counter inside the shared pointer; when the counter became zero, we call
  27. * `CFRelease` on the object. In this model, one bump of ARC-managed counter is
  28. * represented as multiple bumps of C++ counter, so we can have multiple
  29. * counters for the same object that form some kind of counters tree.
  30. */
  31. inline std::shared_ptr<void> wrapManagedObject(id object)
  32. {
  33. return std::shared_ptr<void>((__bridge_retained void *)object, CFRelease);
  34. }
  35. inline id unwrapManagedObject(std::shared_ptr<void> const &object)
  36. {
  37. return (__bridge id)object.get();
  38. }
  39. inline std::shared_ptr<void> wrapManagedObjectWeakly(id object)
  40. {
  41. RCTInternalGenericWeakWrapper *weakWrapper = [RCTInternalGenericWeakWrapper new];
  42. weakWrapper.object = object;
  43. return wrapManagedObject(weakWrapper);
  44. }
  45. inline id unwrapManagedObjectWeakly(std::shared_ptr<void> const &object)
  46. {
  47. RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(object);
  48. assert(weakWrapper && "`RCTInternalGenericWeakWrapper` instance must not be `nil`.");
  49. return weakWrapper.object;
  50. }
  51. } // namespace react
  52. } // namespace facebook
  53. #endif
  54. #endif