首页 > 解决方案 > 在 SwiftUI 中,是否可以仅对某个 os 目标使用修饰符?

问题描述

再会!在 SwiftUI 中,是否可以仅对某个 os 目标使用修饰符?在下面的代码中,我想仅将修饰符 .listStyle(SidebarListStyle()) 用于 MacOS 目标,因为它不存在于 iOS 目标中。谢谢你的帮助。

import SwiftUI

struct ContentView: View {

  @State var selection: Int?

  var body: some View {

    HStack() {
      NavigationView {
        List () {
          NavigationLink(destination: FirstView(), tag: 0, selection: self.$selection) {
            Text("Click Me To Display The First View")
          } // End Navigation Link

          NavigationLink(destination: SecondView(), tag: 1, selection: self.$selection) {
            Text("Click Me To Display The Second View")
          } // End Navigation Link

        } // End list
        .frame(minWidth: 350, maxWidth: 350)
        .onAppear {
            self.selection = 0
        }

      } // End NavigationView
        .listStyle(SidebarListStyle())
        .frame(maxWidth: .infinity, maxHeight: .infinity)

    } // End HStack
  } // End some View
} // End ContentView

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

标签: iosmacosswiftuitargetmodifier

解决方案


您可以创建一个View扩展并像这样使用它:

List {
    // ...
}
.ifOS(.macOS) {
    $0.listStyle(SidebarListStyle())
}

这是实现:

enum OperatingSystem {
    case macOS
    case iOS
    case tvOS
    case watchOS

    #if os(macOS)
    static let current = macOS
    #elseif os(iOS)
    static let current = iOS
    #elseif os(tvOS)
    static let current = tvOS
    #elseif os(watchOS)
    static let current = watchOS
    #else
    #error("Unsupported platform")
    #endif
}

extension View {
    /**
    Conditionally apply modifiers depending on the target operating system.

    ```
    struct ContentView: View {
        var body: some View {
            Text("Unicorn")
                .font(.system(size: 10))
                .ifOS(.macOS, .tvOS) {
                    $0.font(.system(size: 20))
                }
        }
    }
    ```
    */
    @ViewBuilder
    func ifOS<Content: View>(
        _ operatingSystems: OperatingSystem...,
        modifier: (Self) -> Content
    ) -> some View {
        if operatingSystems.contains(OperatingSystem.current) {
            modifier(self)
        } else {
            self
        }
    }
}

但是,如果您尝试使用并非适用于所有目标平台的方法,这将不起作用。完成这项工作的唯一方法是#if os(…)直接使用。

我有一个扩展,可以更轻松地做到这一点:

extension View {
    /**
    Modify the view in a closure. This can be useful when you need to conditionally apply a modifier that is unavailable on certain platforms.

    For example, imagine this code needing to run on macOS too where `View#actionSheet()` is not available:

    ```
    struct ContentView: View {
        var body: some View {
            Text("Unicorn")
                .modify {
                    #if os(iOS)
                    $0.actionSheet(…)
                    #else
                    $0
                    #endif
                }
        }
    }
    ```
    */
    func modify<T: View>(@ViewBuilder modifier: (Self) -> T) -> T {
        modifier(self)
    }
}

推荐阅读