This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
使用 SwiftUI 扩展 学习如何创建与 Expo UI 集成的自定义 SwiftUI 组件和修改器。
Recommended version:
~57.0.22
本指南说明如何使用 Expo Modules API 创建与 Expo UI 集成的自定义 SwiftUI 组件和修饰符。
🌐 This guide explains how to use the Expo Modules API to create custom SwiftUI components and modifiers that integrate with Expo UI.
2.
开发版本
自定义 Expo 模块包含原生代码,Expo Go 无法加载。请创建你的应用的开发构建 。
创建自定义组件
🌐 Creating a custom component
项目设置
🌐 Project setup
1
在你的项目中创建一个本地 Expo 模块:
🌐 Create a local Expo module in your project:
- npx create-expo-module@latest --local my-ui
2
在你的模块的 podspec 文件中将 ExpoUI 添加为依赖:
🌐 Add ExpoUI as a dependency in your module's podspec file:
modules/my-ui/ios/MyUi.podspec Pod:: Spec . new do | s|
s. name = 'MyUi'
s. version = '1.0.0'
s. summary = 'Custom UI components extending Expo UI'
s. dependency 'ExpoUI'
end
创建一个 SwiftUI 视图
🌐 Creating a SwiftUI view
3
创建一个由两部分组成的 SwiftUI 视图:
🌐 Create your SwiftUI view with two parts:
Props 类 :从 ExpoUI 扩展 UIBaseViewProps 以自动支持 modifiers 属性
View 结构体 :遵循 ExpoSwiftUI.View 协议,该协议要求一个 @ObservedObject props 属性和一个 body
modules/my-ui/ios/MyCustomView.swift import SwiftUI
import ExpoModulesCore
import ExpoUI
final class MyCustomViewProps : UIBaseViewProps {
@Field var title: String = ""
}
struct MyCustomView : ExpoSwiftUI . View {
@ObservedObject public var props: MyCustomViewProps
var body: some View {
VStack {
Text ( props. title)
. font ( . headline)
Children ( )
}
}
}
4
使用 ExpoUIView 在你的模块中注册视图。这会将你的 SwiftUI 视图封装为支持修饰符,并使其可供 JavaScript 使用:
🌐 Register the view in your module using ExpoUIView. This wraps your SwiftUI view with modifier support and makes it available to JavaScript:
modules/my-ui/ios/MyUiModule.swift import ExpoModulesCore
import ExpoUI
public class MyUiModule : Module {
public func definition ( ) -> ModuleDefinition {
Name ( "MyUi" )
ExpoUIView ( MyCustomView . self )
}
}
5
创建一个封装组件,将修饰符与事件处理连接起来。createViewModifierEventListener 工具使基于事件的修饰符如 onTapGesture 和 onAppear 可以在你的自定义视图中使用:
🌐 Create a wrapper component that connects modifiers with event handling. The createViewModifierEventListener utility enables event-based modifiers like onTapGesture and onAppear to work with your custom view:
modules/my-ui/src/MyCustomView.tsx import { requireNativeView } from 'expo' ;
import { type CommonViewModifierProps } from '@expo/ui/swift-ui' ;
import { createViewModifierEventListener } from '@expo/ui/swift-ui/modifiers' ;
export interface MyCustomViewProps extends CommonViewModifierProps {
title: string ;
children? : React . ReactNode ;
}
const NativeMyCustomView = requireNativeView < MyCustomViewProps> (
'MyUi' ,
'MyCustomView'
) ;
export function MyCustomView ( {
modifiers,
... restProps
} : MyCustomViewProps ) {
return (
< NativeMyCustomView
modifiers = { modifiers}
{ ... ( modifiers
? createViewModifierEventListener ( modifiers)
: undefined ) }
{ ... restProps}
/>
) ;
}
6
从你的模块入口导出组件:
🌐 Export the component from your module's entry point:
export {
MyCustomView,
type MyCustomViewProps ,
} from './src/MyCustomView' ;
使用自定义组件
🌐 Using your custom component
信息 将本地源文件添加到本地模块并不会将其添加到 iOS 项目中。在重新构建之前运行 npx expo prebuild。否则,构建会因 cannot find 'MyCustomView' in scope 而失败。
你的自定义组件现在可以与所有 ExpoUI 内置修饰符一起使用:
🌐 Your custom component now works with all ExpoUI built-in modifiers:
import { Host , Text } from '@expo/ui/swift-ui' ;
import {
padding,
cornerRadius,
background,
} from '@expo/ui/swift-ui/modifiers' ;
import { MyCustomView } from '../../modules/my-ui' ;
export default function Index ( ) {
return (
< Host style = { { flex: 1 } } >
< MyCustomView
title = " 你好,世界"
modifiers = { [
padding ( { all: 16 } ) ,
background ( '#f0f0f0' ) ,
cornerRadius ( 12 ) ,
] } >
< Text > Child content </ Text >
</ MyCustomView >
</ Host >
) ;
}
创建自定义修改器
🌐 Creating custom modifiers
你也可以创建适用于任何 Expo UI 组件的自定义修改器。
🌐 You can also create custom modifiers that work with any Expo UI component.
信息 修饰符是 SwiftUI 用于配置视图的方式,可用于样式、布局、行为等。更多信息请参阅苹果的 ViewModifier 文档 。
本地修饰符实现
🌐 Native modifier implementation
1
创建一个符合 ViewModifier 和 Record 的修饰符结构体:
🌐 Create a modifier struct that conforms to ViewModifier and Record:
modules/my-ui/ios/CustomBorderModifier.swift import SwiftUI
import ExpoModulesCore
import ExpoUI
struct CustomBorderModifier : ViewModifier , Record {
@Field var color: Color = . red
@Field var width: CGFloat = 2
@Field var cornerRadius: CGFloat = 0
func body ( content: Content ) -> some View {
content
. overlay (
RoundedRectangle ( cornerRadius: cornerRadius)
. stroke ( color, lineWidth: width)
)
}
}
信息 这会添加第二个本地源文件,所以在重新构建之前再次运行 npx expo prebuild。
2
在模块定义中使用 ViewModifierRegistry 注册你的修改器。使用 OnCreate 进行注册,使用 OnDestroy 进行注销,以避免与 SwiftUI 渲染线程的竞争条件:
🌐 Register your modifier with ViewModifierRegistry in your module definition. Use OnCreate to register and OnDestroy to unregister to avoid race conditions with the SwiftUI render thread:
modules/my-ui/ios/MyUiModule.swift import ExpoModulesCore
import ExpoUI
public class MyUiModule : Module {
public func definition ( ) -> ModuleDefinition {
Name ( "MyUi" )
OnCreate {
ViewModifierRegistry . register ( "customBorder" ) { params, appContext, _ in
return try CustomBorderModifier ( from: params, appContext: appContext)
}
}
OnDestroy {
ViewModifierRegistry . unregister ( "customBorder" )
}
ExpoUIView ( MyCustomView . self )
}
}
JavaScript 修改函数
🌐 JavaScript modifier function
3
创建一个生成修改器配置的 TypeScript 函数:
🌐 Create a TypeScript function that generates the modifier config:
modules/my-ui/src/modifiers.ts import { createModifier } from '@expo/ui/swift-ui/modifiers' ;
export const customBorder = ( params: {
color? : string ;
width? : number ;
cornerRadius? : number ;
} ) => createModifier ( 'customBorder' , params) ;
4
从你的模块导出修改器:
🌐 Export the modifier from your module:
export {
MyCustomView,
type MyCustomViewProps ,
} from './src/MyCustomView' ;
export { customBorder } from './src/modifiers' ;
使用自定义修饰符
🌐 Using custom modifiers
你的自定义修改器适用于任何 ExpoUI 组件:
🌐 Your custom modifier works with any ExpoUI component:
import { Host , Text , VStack } from '@expo/ui/swift-ui' ;
import { padding } from '@expo/ui/swift-ui/modifiers' ;
import { customBorder } from '../../modules/my-ui' ;
export default function Index ( ) {
return (
< Host style = { { flex: 1 } } >
< VStack
modifiers = { [
padding ( { all: 20 } ) ,
customBorder ( {
color: '#FF6B35' ,
width: 3 ,
cornerRadius: 8 ,
} ) ,
] } >
< Text > This has a custom border! </ Text >
</ VStack >
</ Host >
) ;
}
下一步
🌐 Next steps
你自定义的组件现在可以和内置的修改器系统一起使用了。从这里你可以:
🌐 Your custom components now work with the built-in modifier system. From here you can:
使用随 Expo UI 提供的 内置 SwiftUI 组件
为应用特定的样式模式构建自定义修饰符
为 React Native 封装第三方 SwiftUI 库
将你的组件作为 npm 包分享给其他人使用