Example of calling swift code from RN
This commit is contained in:
parent
1a9884e0e9
commit
151ed6d78b
12 changed files with 86 additions and 6 deletions
30
App.tsx
30
App.tsx
|
|
@ -1,12 +1,13 @@
|
||||||
import { NewAppScreen } from '@react-native/new-app-screen'
|
import { NewAppScreen } from '@react-native/new-app-screen'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { StatusBar, Text, StyleSheet, useColorScheme, ScrollView } from 'react-native'
|
import { StatusBar, Text, StyleSheet, useColorScheme, ScrollView, Button, Alert } from 'react-native'
|
||||||
import { NativeEventEmitter, NativeModules } from 'react-native'
|
import { NativeEventEmitter, NativeModules } from 'react-native'
|
||||||
|
|
||||||
const { Emitter } = NativeModules
|
const { Emitter, TestingServiceModule } = NativeModules
|
||||||
|
|
||||||
import { requireNativeComponent } from 'react-native'
|
import { requireNativeComponent } from 'react-native'
|
||||||
import type { StyleProp, ViewStyle } from 'react-native'
|
import type { StyleProp, ViewStyle } from 'react-native'
|
||||||
|
|
||||||
type CustomButtonProps = {
|
type CustomButtonProps = {
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}
|
}
|
||||||
|
|
@ -15,9 +16,23 @@ const BaseButton = requireNativeComponent<CustomButtonProps>('BaseButton')
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const isDarkMode = useColorScheme() === 'dark'
|
const isDarkMode = useColorScheme() === 'dark'
|
||||||
const [message, setMessage] = useState(null)
|
const [message, setMessage] = useState<string|null>(null)
|
||||||
const [color, setColor] = useState("#FFF")
|
const [color, setColor] = useState("#FFF")
|
||||||
|
|
||||||
|
|
||||||
|
const onPress = async () => {
|
||||||
|
if (!TestingServiceModule?.greet) {
|
||||||
|
Alert.alert('Module not found', 'MyNativeModule is not linked or not exported.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const result = await TestingServiceModule.greet('John')
|
||||||
|
setMessage(result);
|
||||||
|
} catch (e) {
|
||||||
|
//Alert.alert('Error', String(e?.message ?? e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const emitter = new NativeEventEmitter(Emitter);
|
const emitter = new NativeEventEmitter(Emitter);
|
||||||
const subscription = emitter.addListener('onMessage', (event) => {
|
const subscription = emitter.addListener('onMessage', (event) => {
|
||||||
|
|
@ -28,6 +43,14 @@ export default function App() {
|
||||||
setColor("#00F")
|
setColor("#00F")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestingServiceModule.greet('John')
|
||||||
|
.then((message: string) => {
|
||||||
|
setMessage(message)
|
||||||
|
})
|
||||||
|
.catch((error: string) => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -41,6 +64,7 @@ export default function App() {
|
||||||
<Text>{message ?? 'Waiting for message...'}</Text>
|
<Text>{message ?? 'Waiting for message...'}</Text>
|
||||||
<CustomButton style={{ height: 200 }} />
|
<CustomButton style={{ height: 200 }} />
|
||||||
<BaseButton style={{ height: 200 }} />
|
<BaseButton style={{ height: 200 }} />
|
||||||
|
<Button title="Call Swift greet()" onPress={onPress} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
|
|
||||||
#import <React/RCTViewManager.h>
|
#import <React/RCTViewManager.h>
|
||||||
|
#import <React/RCTBridgeModule.h>
|
||||||
|
|
|
||||||
31
ios/Native/Application/Services/TestingService.swift
Normal file
31
ios/Native/Application/Services/TestingService.swift
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// TestingService.swift
|
||||||
|
// RNPlayground
|
||||||
|
//
|
||||||
|
// Created by Artur Gurgul on 03/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import React
|
||||||
|
|
||||||
|
@objc(TestingServiceModule)
|
||||||
|
class TestingServiceModule: NSObject {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func greet(_ name: String,
|
||||||
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||||
|
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||||
|
let message = "Hello, \(name)! From Swift."
|
||||||
|
resolve(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func constantsToExport() -> [AnyHashable: Any]! {
|
||||||
|
return ["greeting": "Hello from Swift"]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
static func requiresMainQueueSetup() -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
17
ios/Native/Application/Services/TestingServiceModuleBridge.m
Normal file
17
ios/Native/Application/Services/TestingServiceModuleBridge.m
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// TestingServiceModuleBridge.m
|
||||||
|
// RNPlayground
|
||||||
|
//
|
||||||
|
// Created by Artur Gurgul on 03/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <React/RCTBridgeModule.h>
|
||||||
|
|
||||||
|
// This tells React Native about the Swift class
|
||||||
|
@interface RCT_EXTERN_MODULE(TestingServiceModule, NSObject)
|
||||||
|
|
||||||
|
RCT_EXTERN_METHOD(greet:(NSString *)name
|
||||||
|
resolver:(RCTPromiseResolveBlock)resolve
|
||||||
|
rejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -16,7 +16,7 @@ final class SharedState: ObservableObject {
|
||||||
private let emitter = EventEmitter.sharedInstance
|
private let emitter = EventEmitter.sharedInstance
|
||||||
|
|
||||||
// SwiftUI => RN => SwiftUI
|
// SwiftUI => RN => SwiftUI
|
||||||
@Published var text1: String = ""
|
@Published var message: String = ""
|
||||||
|
|
||||||
func send(message: String) {
|
func send(message: String) {
|
||||||
emitter.send(message: message)
|
emitter.send(message: message)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ struct BaseButton: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button("SwiftUI Button") {
|
Button("SwiftUI Button") {
|
||||||
sharedState.text1 = "Clicked in SwiftUI button that was created in RN"
|
sharedState.message = "Clicked in SwiftUI button that was created in RN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
//
|
||||||
|
// CustomButtonManager.m
|
||||||
|
// RNPlayground
|
||||||
|
//
|
||||||
|
// Created by Artur Gurgul on 02/08/2025.
|
||||||
|
//
|
||||||
|
|
||||||
#import <React/RCTViewManager.h>
|
#import <React/RCTViewManager.h>
|
||||||
|
|
||||||
@interface RCT_EXTERN_MODULE(CustomButtonManager, RCTViewManager)
|
@interface RCT_EXTERN_MODULE(CustomButtonManager, RCTViewManager)
|
||||||
|
|
@ -18,7 +18,7 @@ struct ToolboxHeader: View {
|
||||||
sharedState.send(message: "hello from Swift!")
|
sharedState.send(message: "hello from Swift!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text("SwiftUI => RN => SwiftUI: \(sharedState.text1)")
|
Text("Message: \(sharedState.message)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue