nitrogen 0.32.2 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@ export function createHybridObjectIntializer() {
10
10
  const umbrellaHeaderName = getUmbrellaHeaderName();
11
11
  const bridgeNamespace = NitroConfig.current.getSwiftBridgeNamespace('swift');
12
12
  const autolinkedHybridObjects = NitroConfig.current.getAutolinkedHybridObjects();
13
- const swiftFunctions = [];
13
+ const swiftRegistrations = [];
14
14
  const cppRegistrations = [];
15
15
  const cppImports = [];
16
16
  let containsSwiftObjects = false;
@@ -28,13 +28,13 @@ export function createHybridObjectIntializer() {
28
28
  if (config?.swift != null) {
29
29
  // Autolink a Swift HybridObject!
30
30
  containsSwiftObjects = true;
31
- const { cppCode, requiredImports, swiftFunction } = createSwiftHybridObjectRegistration({
31
+ const { cppCode, requiredImports, swiftRegistrationClass } = createSwiftHybridObjectRegistration({
32
32
  hybridObjectName: hybridObjectName,
33
33
  swiftClassName: config.swift,
34
34
  });
35
35
  cppImports.push(...requiredImports);
36
36
  cppRegistrations.push(cppCode);
37
- swiftFunctions.push(swiftFunction);
37
+ swiftRegistrations.push(swiftRegistrationClass);
38
38
  }
39
39
  }
40
40
  if (cppRegistrations.length === 0) {
@@ -72,10 +72,31 @@ ${imports}
72
72
  const swiftCode = `
73
73
  ${createFileMetadataString(`${autolinkingClassName}.swift`)}
74
74
 
75
+ import NitroModules
76
+
77
+ // TODO: Use empty enums once Swift supports exporting them as namespaces
78
+ // See: https://github.com/swiftlang/swift/pull/83616
75
79
  public final class ${autolinkingClassName} {
76
80
  public typealias bridge = ${bridgeNamespace}
77
81
 
78
- ${indent(swiftFunctions.join('\n\n'), ' ')}
82
+ private protocol AutolinkedClass {
83
+ associatedtype T
84
+ /**
85
+ * Creates an instance of the Swift class that implements the HybridObject's spec,
86
+ * and wraps it in a Swift class that can directly interop with C++.
87
+ *
88
+ * This is generated by Nitrogen and will initialize the class specified
89
+ * in the \`"autolinking"\` property of \`nitro.json\`.
90
+ */
91
+ static func create() -> T
92
+ /**
93
+ * Returns whether this concrete implementation is also
94
+ * conforming to the \`RecyclableView\` protocol, or not.
95
+ */
96
+ static var isRecyclableHybridView: Bool { get }
97
+ }
98
+
99
+ ${indent(swiftRegistrations.join('\n\n'), ' ')}
79
100
  }
80
101
  `.trim();
81
102
  return [
@@ -40,14 +40,14 @@ export function createSwiftHybridObject(spec) {
40
40
  baseMembers.push(`
41
41
  public ${hasBaseClass ? 'override func' : 'func'} getCxxWrapper() -> ${name.HybridTSpecCxx} {
42
42
  #if DEBUG
43
- guard self is ${name.HybridTSpec} else {
43
+ guard self is any ${name.HybridTSpec} else {
44
44
  fatalError("\`self\` is not a \`${name.HybridTSpec}\`! Did you accidentally inherit from \`${name.HybridTSpec}_base\` instead of \`${name.HybridTSpec}\`?")
45
45
  }
46
46
  #endif
47
47
  if let cxxWrapper = self.cxxWrapper {
48
48
  return cxxWrapper
49
49
  } else {
50
- let cxxWrapper = ${name.HybridTSpecCxx}(self as! ${name.HybridTSpec})
50
+ let cxxWrapper = ${name.HybridTSpecCxx}(self as! any ${name.HybridTSpec})
51
51
  self.cxxWrapper = cxxWrapper
52
52
  return cxxWrapper
53
53
  }
@@ -41,6 +41,11 @@ public final func beforeUpdate() {
41
41
  public final func afterUpdate() {
42
42
  __implementation.afterUpdate()
43
43
  }
44
+ `.trim(), `
45
+ public final func maybePrepareForRecycle() {
46
+ guard let recyclable = __implementation as? RecyclableView else { return }
47
+ recyclable.prepareForRecycle()
48
+ }
44
49
  `.trim());
45
50
  }
46
51
  const hybridObject = new HybridObjectType(spec);
@@ -11,9 +11,10 @@ interface Props {
11
11
  }
12
12
  interface SwiftHybridObjectRegistration {
13
13
  cppCode: string;
14
- swiftFunction: string;
14
+ swiftRegistrationClass: string;
15
15
  requiredImports: SourceImport[];
16
16
  }
17
+ export declare function getAutolinkingNamespace(): string;
17
18
  export declare function getHybridObjectConstructorCall(hybridObjectName: string): string;
18
19
  export declare function createSwiftHybridObjectRegistration({ hybridObjectName, swiftClassName, }: Props): SwiftHybridObjectRegistration;
19
20
  export {};
@@ -3,27 +3,29 @@ import { indent } from '../../utils.js';
3
3
  import { getHybridObjectName } from '../getHybridObjectName.js';
4
4
  import { HybridObjectType } from '../types/HybridObjectType.js';
5
5
  import { SwiftCxxBridgedType } from './SwiftCxxBridgedType.js';
6
- export function getHybridObjectConstructorCall(hybridObjectName) {
6
+ export function getAutolinkingNamespace() {
7
7
  const swiftNamespace = NitroConfig.current.getIosModuleName();
8
8
  const autolinkingClassName = `${swiftNamespace}Autolinking`;
9
- return `${swiftNamespace}::${autolinkingClassName}::create${hybridObjectName}();`;
9
+ return `${swiftNamespace}::${autolinkingClassName}`;
10
+ }
11
+ export function getHybridObjectConstructorCall(hybridObjectName) {
12
+ const namespace = getAutolinkingNamespace();
13
+ return `${namespace}::${hybridObjectName}::create();`;
10
14
  }
11
15
  export function createSwiftHybridObjectRegistration({ hybridObjectName, swiftClassName, }) {
12
- const { HybridTSpecCxx, HybridTSpecSwift, HybridTSpec } = getHybridObjectName(hybridObjectName);
16
+ const { HybridTSpecSwift } = getHybridObjectName(hybridObjectName);
13
17
  const type = new HybridObjectType(hybridObjectName, 'swift', [], NitroConfig.current);
14
18
  const bridge = new SwiftCxxBridgedType(type);
15
19
  return {
16
- swiftFunction: `
17
- /**
18
- * Creates an instance of a Swift class that implements \`${HybridTSpec}\`,
19
- * and wraps it in a Swift class that can directly interop with C++ (\`${HybridTSpecCxx}\`)
20
- *
21
- * This is generated by Nitrogen and will initialize the class specified
22
- * in the \`"autolinking"\` property of \`nitro.json\` (in this case, \`${swiftClassName}\`).
23
- */
24
- public static func create${hybridObjectName}() -> ${bridge.getTypeCode('swift')} {
25
- let hybridObject = ${swiftClassName}()
26
- return ${indent(bridge.parseFromSwiftToCpp('hybridObject', 'swift'), ' ')}
20
+ swiftRegistrationClass: `
21
+ public final class ${hybridObjectName}: AutolinkedClass {
22
+ public static func create() -> ${bridge.getTypeCode('swift')} {
23
+ let hybridObject = ${swiftClassName}()
24
+ return ${indent(bridge.parseFromSwiftToCpp('hybridObject', 'swift'), ' ')}
25
+ }
26
+ public static var isRecyclableHybridView: Bool {
27
+ return ${swiftClassName}.self is any RecyclableView.Type
28
+ }
27
29
  }
28
30
  `.trim(),
29
31
  requiredImports: [
@@ -26,13 +26,20 @@ import com.facebook.react.uimanager.ReactStylesDiffMap
26
26
  import com.facebook.react.uimanager.SimpleViewManager
27
27
  import com.facebook.react.uimanager.StateWrapper
28
28
  import com.facebook.react.uimanager.ThemedReactContext
29
+ import com.margelo.nitro.R.id.associated_hybrid_view_tag
30
+ import com.margelo.nitro.views.RecyclableView
29
31
  import ${javaNamespace}.*
30
32
 
31
33
  /**
32
34
  * Represents the React Native \`ViewManager\` for the "${spec.name}" Nitro HybridView.
33
35
  */
34
36
  open class ${manager}: SimpleViewManager<View>() {
35
- private val views = hashMapOf<View, ${viewImplementation}>()
37
+ init {
38
+ if (RecyclableView::class.java.isAssignableFrom(${viewImplementation}::class.java)) {
39
+ // Enable view recycling
40
+ super.setupViewRecycling()
41
+ }
42
+ }
36
43
 
37
44
  override fun getName(): String {
38
45
  return "${spec.name}"
@@ -41,17 +48,13 @@ open class ${manager}: SimpleViewManager<View>() {
41
48
  override fun createViewInstance(reactContext: ThemedReactContext): View {
42
49
  val hybridView = ${viewImplementation}(reactContext)
43
50
  val view = hybridView.view
44
- views[view] = hybridView
51
+ view.setTag(associated_hybrid_view_tag, hybridView)
45
52
  return view
46
53
  }
47
54
 
48
- override fun onDropViewInstance(view: View) {
49
- super.onDropViewInstance(view)
50
- views.remove(view)
51
- }
52
-
53
55
  override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
54
- val hybridView = views[view] ?: throw Error("Couldn't find view $view in local views table!")
56
+ val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
57
+ ?: throw Error("Couldn't find view $view in local views table!")
55
58
 
56
59
  // 1. Update each prop individually
57
60
  hybridView.beforeUpdate()
@@ -62,10 +65,21 @@ open class ${manager}: SimpleViewManager<View>() {
62
65
  return super.updateState(view, props, stateWrapper)
63
66
  }
64
67
 
65
- protected override fun setupViewRecycling() {
66
- // TODO: Recycling should be controllable by the user. WIP, but disabled for now.
67
- // By not calling \`super.setupViewRecycling()\`, we effectively
68
- // disable view recycling for now.
68
+ protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
69
+ super.prepareToRecycleView(reactContext, view)
70
+ val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
71
+ ?: return null
72
+
73
+ @Suppress("USELESS_IS_CHECK")
74
+ if (hybridView is RecyclableView) {
75
+ // Recycle in it's implementation
76
+ hybridView.prepareForRecycle()
77
+
78
+ // Maybe update the view if it changed
79
+ return hybridView.view
80
+ } else {
81
+ return null
82
+ }
69
83
  }
70
84
  }
71
85
  `.trim();
@@ -2,7 +2,7 @@ import { createViewComponentShadowNodeFiles, getViewComponentNames, } from '../C
2
2
  import { createFileMetadataString, escapeCppName, } from '../../syntax/helpers.js';
3
3
  import { getUmbrellaHeaderName } from '../../autolinking/ios/createSwiftUmbrellaHeader.js';
4
4
  import { getHybridObjectName } from '../../syntax/getHybridObjectName.js';
5
- import { getHybridObjectConstructorCall } from '../../syntax/swift/SwiftHybridObjectRegistration.js';
5
+ import { getAutolinkingNamespace, getHybridObjectConstructorCall, } from '../../syntax/swift/SwiftHybridObjectRegistration.js';
6
6
  import { indent } from '../../utils.js';
7
7
  import { SwiftCxxBridgedType } from '../../syntax/swift/SwiftCxxBridgedType.js';
8
8
  export function createSwiftHybridViewManager(spec) {
@@ -68,11 +68,6 @@ using namespace ${namespace}::views;
68
68
  return react::concreteComponentDescriptorProvider<${descriptorClassName}>();
69
69
  }
70
70
 
71
- + (BOOL)shouldBeRecycled {
72
- // TODO: Recycling should be controllable by the user. WIP, but disabled for now.
73
- return NO;
74
- }
75
-
76
71
  - (instancetype) init {
77
72
  if (self = [super init]) {
78
73
  std::shared_ptr<${HybridTSpec}> hybridView = ${getHybridObjectConstructorCall(spec.name)}
@@ -122,6 +117,16 @@ using namespace ${namespace}::views;
122
117
  [super updateProps:props oldProps:oldProps];
123
118
  }
124
119
 
120
+ + (BOOL)shouldBeRecycled {
121
+ return ${getAutolinkingNamespace()}::${spec.name}::isRecyclableHybridView();
122
+ }
123
+
124
+ - (void)prepareForRecycle {
125
+ [super prepareForRecycle];
126
+ ${swiftNamespace}::${HybridTSpecCxx}& swiftPart = _hybridView->getSwiftPart();
127
+ swiftPart.maybePrepareForRecycle();
128
+ }
129
+
125
130
  @end
126
131
  `;
127
132
  return [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitrogen",
3
- "version": "0.32.2",
3
+ "version": "0.33.0",
4
4
  "description": "The code-generator for react-native-nitro-modules.",
5
5
  "main": "lib/index",
6
6
  "types": "lib/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "chalk": "^5.3.0",
38
- "react-native-nitro-modules": "^0.32.2",
38
+ "react-native-nitro-modules": "^0.33.0",
39
39
  "ts-morph": "^27.0.0",
40
40
  "yargs": "^18.0.0",
41
41
  "zod": "^4.0.5"
@@ -18,7 +18,7 @@ export function createHybridObjectIntializer(): [ObjcFile, SwiftFile] | [] {
18
18
  const autolinkedHybridObjects =
19
19
  NitroConfig.current.getAutolinkedHybridObjects()
20
20
 
21
- const swiftFunctions: string[] = []
21
+ const swiftRegistrations: string[] = []
22
22
  const cppRegistrations: string[] = []
23
23
  const cppImports: SourceImport[] = []
24
24
  let containsSwiftObjects = false
@@ -37,14 +37,14 @@ export function createHybridObjectIntializer(): [ObjcFile, SwiftFile] | [] {
37
37
  if (config?.swift != null) {
38
38
  // Autolink a Swift HybridObject!
39
39
  containsSwiftObjects = true
40
- const { cppCode, requiredImports, swiftFunction } =
40
+ const { cppCode, requiredImports, swiftRegistrationClass } =
41
41
  createSwiftHybridObjectRegistration({
42
42
  hybridObjectName: hybridObjectName,
43
43
  swiftClassName: config.swift,
44
44
  })
45
45
  cppImports.push(...requiredImports)
46
46
  cppRegistrations.push(cppCode)
47
- swiftFunctions.push(swiftFunction)
47
+ swiftRegistrations.push(swiftRegistrationClass)
48
48
  }
49
49
  }
50
50
 
@@ -86,10 +86,31 @@ ${imports}
86
86
  const swiftCode = `
87
87
  ${createFileMetadataString(`${autolinkingClassName}.swift`)}
88
88
 
89
+ import NitroModules
90
+
91
+ // TODO: Use empty enums once Swift supports exporting them as namespaces
92
+ // See: https://github.com/swiftlang/swift/pull/83616
89
93
  public final class ${autolinkingClassName} {
90
94
  public typealias bridge = ${bridgeNamespace}
91
95
 
92
- ${indent(swiftFunctions.join('\n\n'), ' ')}
96
+ private protocol AutolinkedClass {
97
+ associatedtype T
98
+ /**
99
+ * Creates an instance of the Swift class that implements the HybridObject's spec,
100
+ * and wraps it in a Swift class that can directly interop with C++.
101
+ *
102
+ * This is generated by Nitrogen and will initialize the class specified
103
+ * in the \`"autolinking"\` property of \`nitro.json\`.
104
+ */
105
+ static func create() -> T
106
+ /**
107
+ * Returns whether this concrete implementation is also
108
+ * conforming to the \`RecyclableView\` protocol, or not.
109
+ */
110
+ static var isRecyclableHybridView: Bool { get }
111
+ }
112
+
113
+ ${indent(swiftRegistrations.join('\n\n'), ' ')}
93
114
  }
94
115
  `.trim()
95
116
 
@@ -49,14 +49,14 @@ export function createSwiftHybridObject(spec: HybridObjectSpec): SourceFile[] {
49
49
  `
50
50
  public ${hasBaseClass ? 'override func' : 'func'} getCxxWrapper() -> ${name.HybridTSpecCxx} {
51
51
  #if DEBUG
52
- guard self is ${name.HybridTSpec} else {
52
+ guard self is any ${name.HybridTSpec} else {
53
53
  fatalError("\`self\` is not a \`${name.HybridTSpec}\`! Did you accidentally inherit from \`${name.HybridTSpec}_base\` instead of \`${name.HybridTSpec}\`?")
54
54
  }
55
55
  #endif
56
56
  if let cxxWrapper = self.cxxWrapper {
57
57
  return cxxWrapper
58
58
  } else {
59
- let cxxWrapper = ${name.HybridTSpecCxx}(self as! ${name.HybridTSpec})
59
+ let cxxWrapper = ${name.HybridTSpecCxx}(self as! any ${name.HybridTSpec})
60
60
  self.cxxWrapper = cxxWrapper
61
61
  return cxxWrapper
62
62
  }
@@ -63,6 +63,12 @@ public final func beforeUpdate() {
63
63
  public final func afterUpdate() {
64
64
  __implementation.afterUpdate()
65
65
  }
66
+ `.trim(),
67
+ `
68
+ public final func maybePrepareForRecycle() {
69
+ guard let recyclable = __implementation as? RecyclableView else { return }
70
+ recyclable.prepareForRecycle()
71
+ }
66
72
  `.trim()
67
73
  )
68
74
  }
@@ -18,24 +18,28 @@ interface Props {
18
18
 
19
19
  interface SwiftHybridObjectRegistration {
20
20
  cppCode: string
21
- swiftFunction: string
21
+ swiftRegistrationClass: string
22
22
  requiredImports: SourceImport[]
23
23
  }
24
24
 
25
+ export function getAutolinkingNamespace() {
26
+ const swiftNamespace = NitroConfig.current.getIosModuleName()
27
+ const autolinkingClassName = `${swiftNamespace}Autolinking`
28
+ return `${swiftNamespace}::${autolinkingClassName}`
29
+ }
30
+
25
31
  export function getHybridObjectConstructorCall(
26
32
  hybridObjectName: string
27
33
  ): string {
28
- const swiftNamespace = NitroConfig.current.getIosModuleName()
29
- const autolinkingClassName = `${swiftNamespace}Autolinking`
30
- return `${swiftNamespace}::${autolinkingClassName}::create${hybridObjectName}();`
34
+ const namespace = getAutolinkingNamespace()
35
+ return `${namespace}::${hybridObjectName}::create();`
31
36
  }
32
37
 
33
38
  export function createSwiftHybridObjectRegistration({
34
39
  hybridObjectName,
35
40
  swiftClassName,
36
41
  }: Props): SwiftHybridObjectRegistration {
37
- const { HybridTSpecCxx, HybridTSpecSwift, HybridTSpec } =
38
- getHybridObjectName(hybridObjectName)
42
+ const { HybridTSpecSwift } = getHybridObjectName(hybridObjectName)
39
43
 
40
44
  const type = new HybridObjectType(
41
45
  hybridObjectName,
@@ -46,17 +50,15 @@ export function createSwiftHybridObjectRegistration({
46
50
  const bridge = new SwiftCxxBridgedType(type)
47
51
 
48
52
  return {
49
- swiftFunction: `
50
- /**
51
- * Creates an instance of a Swift class that implements \`${HybridTSpec}\`,
52
- * and wraps it in a Swift class that can directly interop with C++ (\`${HybridTSpecCxx}\`)
53
- *
54
- * This is generated by Nitrogen and will initialize the class specified
55
- * in the \`"autolinking"\` property of \`nitro.json\` (in this case, \`${swiftClassName}\`).
56
- */
57
- public static func create${hybridObjectName}() -> ${bridge.getTypeCode('swift')} {
58
- let hybridObject = ${swiftClassName}()
59
- return ${indent(bridge.parseFromSwiftToCpp('hybridObject', 'swift'), ' ')}
53
+ swiftRegistrationClass: `
54
+ public final class ${hybridObjectName}: AutolinkedClass {
55
+ public static func create() -> ${bridge.getTypeCode('swift')} {
56
+ let hybridObject = ${swiftClassName}()
57
+ return ${indent(bridge.parseFromSwiftToCpp('hybridObject', 'swift'), ' ')}
58
+ }
59
+ public static var isRecyclableHybridView: Bool {
60
+ return ${swiftClassName}.self is any RecyclableView.Type
61
+ }
60
62
  }
61
63
  `.trim(),
62
64
  requiredImports: [
@@ -46,13 +46,20 @@ import com.facebook.react.uimanager.ReactStylesDiffMap
46
46
  import com.facebook.react.uimanager.SimpleViewManager
47
47
  import com.facebook.react.uimanager.StateWrapper
48
48
  import com.facebook.react.uimanager.ThemedReactContext
49
+ import com.margelo.nitro.R.id.associated_hybrid_view_tag
50
+ import com.margelo.nitro.views.RecyclableView
49
51
  import ${javaNamespace}.*
50
52
 
51
53
  /**
52
54
  * Represents the React Native \`ViewManager\` for the "${spec.name}" Nitro HybridView.
53
55
  */
54
56
  open class ${manager}: SimpleViewManager<View>() {
55
- private val views = hashMapOf<View, ${viewImplementation}>()
57
+ init {
58
+ if (RecyclableView::class.java.isAssignableFrom(${viewImplementation}::class.java)) {
59
+ // Enable view recycling
60
+ super.setupViewRecycling()
61
+ }
62
+ }
56
63
 
57
64
  override fun getName(): String {
58
65
  return "${spec.name}"
@@ -61,17 +68,13 @@ open class ${manager}: SimpleViewManager<View>() {
61
68
  override fun createViewInstance(reactContext: ThemedReactContext): View {
62
69
  val hybridView = ${viewImplementation}(reactContext)
63
70
  val view = hybridView.view
64
- views[view] = hybridView
71
+ view.setTag(associated_hybrid_view_tag, hybridView)
65
72
  return view
66
73
  }
67
74
 
68
- override fun onDropViewInstance(view: View) {
69
- super.onDropViewInstance(view)
70
- views.remove(view)
71
- }
72
-
73
75
  override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? {
74
- val hybridView = views[view] ?: throw Error("Couldn't find view $view in local views table!")
76
+ val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
77
+ ?: throw Error("Couldn't find view $view in local views table!")
75
78
 
76
79
  // 1. Update each prop individually
77
80
  hybridView.beforeUpdate()
@@ -82,10 +85,21 @@ open class ${manager}: SimpleViewManager<View>() {
82
85
  return super.updateState(view, props, stateWrapper)
83
86
  }
84
87
 
85
- protected override fun setupViewRecycling() {
86
- // TODO: Recycling should be controllable by the user. WIP, but disabled for now.
87
- // By not calling \`super.setupViewRecycling()\`, we effectively
88
- // disable view recycling for now.
88
+ protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? {
89
+ super.prepareToRecycleView(reactContext, view)
90
+ val hybridView = view.getTag(associated_hybrid_view_tag) as? ${viewImplementation}
91
+ ?: return null
92
+
93
+ @Suppress("USELESS_IS_CHECK")
94
+ if (hybridView is RecyclableView) {
95
+ // Recycle in it's implementation
96
+ hybridView.prepareForRecycle()
97
+
98
+ // Maybe update the view if it changed
99
+ return hybridView.view
100
+ } else {
101
+ return null
102
+ }
89
103
  }
90
104
  }
91
105
  `.trim()
@@ -10,7 +10,10 @@ import {
10
10
  } from '../../syntax/helpers.js'
11
11
  import { getUmbrellaHeaderName } from '../../autolinking/ios/createSwiftUmbrellaHeader.js'
12
12
  import { getHybridObjectName } from '../../syntax/getHybridObjectName.js'
13
- import { getHybridObjectConstructorCall } from '../../syntax/swift/SwiftHybridObjectRegistration.js'
13
+ import {
14
+ getAutolinkingNamespace,
15
+ getHybridObjectConstructorCall,
16
+ } from '../../syntax/swift/SwiftHybridObjectRegistration.js'
14
17
  import { indent } from '../../utils.js'
15
18
  import { SwiftCxxBridgedType } from '../../syntax/swift/SwiftCxxBridgedType.js'
16
19
 
@@ -89,11 +92,6 @@ using namespace ${namespace}::views;
89
92
  return react::concreteComponentDescriptorProvider<${descriptorClassName}>();
90
93
  }
91
94
 
92
- + (BOOL)shouldBeRecycled {
93
- // TODO: Recycling should be controllable by the user. WIP, but disabled for now.
94
- return NO;
95
- }
96
-
97
95
  - (instancetype) init {
98
96
  if (self = [super init]) {
99
97
  std::shared_ptr<${HybridTSpec}> hybridView = ${getHybridObjectConstructorCall(spec.name)}
@@ -143,6 +141,16 @@ using namespace ${namespace}::views;
143
141
  [super updateProps:props oldProps:oldProps];
144
142
  }
145
143
 
144
+ + (BOOL)shouldBeRecycled {
145
+ return ${getAutolinkingNamespace()}::${spec.name}::isRecyclableHybridView();
146
+ }
147
+
148
+ - (void)prepareForRecycle {
149
+ [super prepareForRecycle];
150
+ ${swiftNamespace}::${HybridTSpecCxx}& swiftPart = _hybridView->getSwiftPart();
151
+ swiftPart.maybePrepareForRecycle();
152
+ }
153
+
146
154
  @end
147
155
  `
148
156