You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:27:52