如何使用 SwiftUI 将条件 ToolbarItems 添加到 NavigationView 工具栏?

How to add conditional ToolbarItems to NavigationView Toolbar with SwiftUI?

我正在尝试将图标按钮添加到 NavigationView 工具栏的前缘 - 但我希望该按钮仅在设备处于横向模式时可见。 (有点像默认 Notes 应用程序的工作方式)

我有以下代码:

var body: some View {
        VStack {
            // ... content display
        }
        .toolbar {
            if UIDevice.current.orientation.isLandscape {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: toggleFullscreen) {
                        if isFullscreen {
                            Image(systemName: "arrow.down.right.and.arrow.up.left")
                        } else {
                            Image(systemName: "arrow.up.left.and.arrow.down.right")
                        }
                    }
                }
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                Button(action: createNewNote) {
                    Image(systemName: "square.and.pencil")
                }
            }
        })
    }

如果我删除工具栏内容中的条件 if 子句,它可以正常工作,但它似乎根本无法识别 if 语句?

然而,VStack 中的 if 语句工作正常。

我得到的具体错误是:

Closure containing control flow statement cannot be used with result builder 'ToolbarContentBuilder'

知道如何解决这个问题吗?


P.S。将我视为一个完整的 SwiftUI 菜鸟。虽然,我精通 React - 所以任何帮助我理解的 React 类比将不胜感激。

您检测设备方向的方式有误SwiftUI实现这一点的一种方法是使用自定义修饰符来检测设备旋转:

Cfr: https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-device-rotation

代码如下所示:

1。创建自定义修饰符:Detecting Device Rotation

// Our custom view modifier to track rotation and call our action
struct DeviceRotationViewModifier: ViewModifier {
    let action: (UIDeviceOrientation) -> Void

    func body(content: Content) -> some View {
        content
            .onAppear()
            .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                action(UIDevice.current.orientation)
            }
    }
}

// A View wrapper to make the modifier easier to use
extension View {
    func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
        self.modifier(DeviceRotationViewModifier(action: action))
    }
}

2。使用创建的修饰符:

struct ContentView: View {
    
    @State private var isFullscreen = false
    @State private var orientation = UIDeviceOrientation.unknown

    var body: some View {
        NavigationView {
            VStack {
                // ... content display
                
            }
            .onRotate { orientation = [=11=] }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    if orientation.isLandscape {
                        Button(action: {}) {
                            if isFullscreen {
                                Image(systemName: "arrow.down.right.and.arrow.up.left")
                            } else {
                                Image(systemName: "arrow.up.left.and.arrow.down.right")
                            }
                        }
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: {}) {
                        Image(systemName: "square.and.pencil")
                    }
                }
                
            }
            
        }
    }
    
}