New Architecture Support
Swiftpatch ships as a TurboModule out of the box. Enable the New Architecture on your project and autolinking does the rest — no codegen invocation required from you.
Enable the New Architecture
iOS
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
Then re-pod:
cd ios && pod install && cd ..
Android
newArchEnabled=true
Then:
cd android && ./gradlew clean && cd ..
Verifying you're on TurboModules
The SDK exposes a runtime flag:
import { IS_TURBO_MODULE_ENABLED } from '@swiftpatch/react-native';
console.log('Using TurboModules:', IS_TURBO_MODULE_ENABLED);
When this is true, every native call goes through JSI directly — no bridge serialization.
Performance
TurboModule calls skip JSON serialization and the bridge. Typical operation costs on a mid-range device:
| Operation | Legacy bridge | TurboModule |
|---|---|---|
checkForUpdate() round trip | 15 ms | 2 ms |
getCurrentBundle() | 8 ms | 1 ms |
getSlotMetadata() | 10 ms | 2 ms |
The SDK also uses the TurboModule's addListener/removeListeners bookkeeping, so native events (download progress, rollback, version-changed) are delivered with minimal overhead.
Codegen
The SDK ships a codegen spec at src/native/NativeSwiftPatchSpec.ts. React Native's codegen consumes it during your app build and generates the native interfaces for iOS and Android. You don't invoke codegen yourself — it runs as part of pod install on iOS and Gradle's generateCodegenArtifactsFromSchema task on Android.
The spec uses only the types codegen allows:
- Primitives (
string,number,boolean). Object,Array<Object>.- Nullable primitives (
T | null). Promise<T>.- No string-literal unions, no
Pick/Omit, no imported types on method signatures.
Rich types (CheckResult, UpdateDescriptor, PatchDescriptor, SlotMetadataShape) live alongside the spec but are not consumed by codegen — they narrow the native return type inside the TypeScript wrapper.
codegenConfig
Your app's package.json does not need a codegenConfig entry for Swiftpatch — the SDK's own package.json declares it:
{
"codegenConfig": {
"name": "RNSwiftPatchSpec",
"type": "modules",
"jsSrcsDir": "src/native",
"ios": { "componentProvider": "" }
}
}
React Native autolinking picks this up and generates the TurboModule stubs in the correct location.
Troubleshooting New Architecture builds
- "Cannot find module 'NativeSwiftPatch'" — codegen didn't run. Re-run
pod install(iOS) or./gradlew clean build(Android). - Duplicate native module — you have both old-arch and new-arch artifacts. Clean everything:
cd ios && rm -rf Pods Podfile.lock && pod install && cd ..andcd android && ./gradlew clean. TurboModuleRegistry.getEnforcing('SwiftPatch') fails— New Architecture is not actually enabled. VerifyRCT_NEW_ARCH_ENABLED=1(iOS) andnewArchEnabled=true(Android).
Fallback to the legacy bridge
If the New Architecture isn't enabled, the SDK automatically falls back to the legacy bridge module. The JavaScript API is identical. You won't notice a difference at the call-site.
Next steps
- iOS setup / Android setup — platform setup.
- Methods — the imperative API (identical on TurboModule and legacy).
- Troubleshooting — general setup issues.