如何避免NavigationView中不同SwiftUI视图的代码重复?
解决代码重复的几种实用方法
方法一:自定义ViewModifier封装导航栏配置
把重复的导航栏设置封装成一个可复用的ViewModifier,这样不管是模拟器的占位文本还是真机的VisionView,都能统一应用这套配置:
// 定义自定义Modifier struct VisionSheetNavigationModifier: ViewModifier { let title: String let onClose: () -> Void func body(content: Content) -> some View { content .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) .toolbar { Button("Close") { onClose() } } } } // 给View扩展便捷调用方法 extension View { func visionSheetNavigation(title: String, onClose: @escaping () -> Void) -> some View { self.modifier(VisionSheetNavigationModifier(title: title, onClose: onClose)) } }
修改后的sheet代码:
.sheet(isPresented: $isVisionPresented) { NavigationView { #if targetEnvironment(simulator) Text("Cannot run Vision framework in Simulator") #else VisionView() #endif .visionSheetNavigation(title: "Sample title") { isVisionPresented = false } } }
这种方式的优势是复用性极强,后续要调整导航栏标题、关闭逻辑或样式,只需要修改VisionSheetNavigationModifier即可。
方法二:提取通用导航容器视图
把整个带导航栏的容器封装成一个独立视图,内部处理环境判断或接受外部传入的内容:
方式A:容器接受外部内容
struct VisionSheetContainer<Content: View>: View { let title: String let onClose: () -> Void let content: Content var body: some View { NavigationView { content .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) .toolbar { Button("Close") { onClose() } } } } }
调用代码:
.sheet(isPresented: $isVisionPresented) { #if targetEnvironment(simulator) VisionSheetContainer(title: "Sample title", onClose: { isVisionPresented = false }) { Text("Cannot run Vision framework in Simulator") } #else VisionSheetContainer(title: "Sample title", onClose: { isVisionPresented = false }) { VisionView() } #endif }
方式B:容器内部处理环境判断
如果模拟器和真机的内容固定,还可以把条件判断也封装到容器里,进一步简化外部调用:
struct VisionSheetContainer: View { let title: String let onClose: () -> Void var body: some View { NavigationView { #if targetEnvironment(simulator) Text("Cannot run Vision framework in Simulator") #else VisionView() #endif .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) .toolbar { Button("Close") { onClose() } } } } }
调用代码会非常简洁:
.sheet(isPresented: $isVisionPresented) { VisionSheetContainer(title: "Sample title") { isVisionPresented = false } }
内容的提问来源于stack exchange,提问作者Lorenzo B
相关产品推荐
相关产品推荐

