在 SwiftUI 中,pos 是否可以只对某个 os 目标使用修饰符?
In SwiftUI, is it possible to use a modifier only for a certain os target?
美好的一天!在 SwiftUI 中,pos 是否可以只对某个 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()
}
}
感谢DoesData给我指路
解决方案是在整个代码周围使用 #is os(macOS),而不仅仅是修饰符本身。
import SwiftUI
struct ContentView: View {
@State var selection: Int?
var body: some View {
#if os(macOS)
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
#elseif os(iOS)
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
.frame(maxWidth: .infinity, maxHeight: .infinity)
} // End HStack
#endif
} // End some View
} // End ContentView
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
你最好这样做:
import SwiftUI
struct ContentView: View {
@State var selection: Int?
var body: some View {
#if targetEnvironment(macCatalyst)
return theList.listStyle(SidebarListStyle())
#else
return theList.navigationViewStyle(DefaultNavigationViewStyle())
#endif
}
var theList: 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
.frame(maxWidth: .infinity, maxHeight: .infinity)
} // End HStack
} // End some View
} // End ContentView
}
WorkingDog,我用一个非常简单的代码尝试了您的 elegante 代码,以根据目标更改文本颜色...但是文本在两个目标上都保持蓝色,在 MacOS 上不会变红!
import SwiftUI
struct ContentView: View {
var body: some View {
#if os(macOS)
return monText.foregroundColor(Color.red)
#elseif os(iOS)
return monText.foregroundColor(Color.blue)
#endif
}
var monText: some View {
Text("Hello, World!")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
您可以创建一个 View
扩展并像这样使用它:
List {
// ...
}
.ifOS(.macOS) {
[=10=].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) {
[=11=].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)
[=12=].actionSheet(…)
#else
[=12=]
#endif
}
}
}
```
*/
func modify<T: View>(@ViewBuilder modifier: (Self) -> T) -> T {
modifier(self)
}
}
Swift 5.5
从Swift5.5版本开始,可以直接对withing修饰符使用add条件
} // End NavigationView
#if os(macOS)
.listStyle(SidebarListStyle())
#else
.navigationViewStyle(DefaultNavigationViewStyle())
#endif
美好的一天!在 SwiftUI 中,pos 是否可以只对某个 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()
}
}
感谢DoesData给我指路
解决方案是在整个代码周围使用 #is os(macOS),而不仅仅是修饰符本身。
import SwiftUI
struct ContentView: View {
@State var selection: Int?
var body: some View {
#if os(macOS)
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
#elseif os(iOS)
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
.frame(maxWidth: .infinity, maxHeight: .infinity)
} // End HStack
#endif
} // End some View
} // End ContentView
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
你最好这样做:
import SwiftUI
struct ContentView: View {
@State var selection: Int?
var body: some View {
#if targetEnvironment(macCatalyst)
return theList.listStyle(SidebarListStyle())
#else
return theList.navigationViewStyle(DefaultNavigationViewStyle())
#endif
}
var theList: 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
.frame(maxWidth: .infinity, maxHeight: .infinity)
} // End HStack
} // End some View
} // End ContentView
}
WorkingDog,我用一个非常简单的代码尝试了您的 elegante 代码,以根据目标更改文本颜色...但是文本在两个目标上都保持蓝色,在 MacOS 上不会变红!
import SwiftUI
struct ContentView: View {
var body: some View {
#if os(macOS)
return monText.foregroundColor(Color.red)
#elseif os(iOS)
return monText.foregroundColor(Color.blue)
#endif
}
var monText: some View {
Text("Hello, World!")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
您可以创建一个 View
扩展并像这样使用它:
List {
// ...
}
.ifOS(.macOS) {
[=10=].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) {
[=11=].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)
[=12=].actionSheet(…)
#else
[=12=]
#endif
}
}
}
```
*/
func modify<T: View>(@ViewBuilder modifier: (Self) -> T) -> T {
modifier(self)
}
}
Swift 5.5
从Swift5.5版本开始,可以直接对withing修饰符使用add条件
} // End NavigationView
#if os(macOS)
.listStyle(SidebarListStyle())
#else
.navigationViewStyle(DefaultNavigationViewStyle())
#endif