Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have a conditional modifier based on the os version in SwiftUI?

Tags:

ios

swift

swiftui

I'm new to programming and I joined StackOverflow today. I hope I can ask based on the guidelines:

I'm starting SwiftUI and it seems it has many code that works only for iOS 17, take a look at this:

if #available(iOS 17.0, *) {
    Text("Hello World")
        .font(.title.bold())
        .multilineTextAlignment(.leading)

        // This modifier only works on iOS 17
        .foregroundStyle(.red)
} else {
    Text("Hello World")
        .font(.title.bold())
        .multilineTextAlignment(.leading)

        .foregroundColor(.red)
}

One of the first things I learned is to not repeat the same code but how can I apply different modifiers easily without repeating the code? something like this:

Text("Hello World")
    .font(.title.bold())
    .multilineTextAlignment(.leading)

  if #available(iOS 17.0, *) {
    .foregroundStyle(.red)
  } else {
    .foregroundColor(.red)
  }

P.S: I have seen posts like this to implement a custom modifier that takes a bool as input, but it can't take the os version in a way that the compiler understands like #available(iOS 17.0, *).

Update

I know we can achieve something similar for the os check like the following, but I'm looking for the check for the version in the same general way:

Text("Hello World")
    .font(.title.bold())
    .multilineTextAlignment(.leading)

  #if os(iOS)
    .foregroundStyle(.red)
  #else
    .foregroundColor(.red)

Thanks for considering my question

like image 486
Trajanos Avatar asked Dec 21 '25 05:12

Trajanos


2 Answers

You can achieve something quite similar with a simple extension:

extension View {
    func apply<V: View>(@ViewBuilder _ block: (Self) -> V) -> V { block(self) }
}

Now you can use it like:

Text("Hello World")
    .font(.title.bold())
    .multilineTextAlignment(.leading)
    .apply {
        if #available(iOS 15.0, *) {
            $0.foregroundStyle(.red)
        } else {
            $0.foregroundColor(.red)
        }
    }

Note that you can apply any modifier on any view you like and it is pretty general as you asked.

like image 200
Mojtaba Hosseini Avatar answered Dec 22 '25 20:12

Mojtaba Hosseini


I think there is a simpler approach to this.

Still using a view modifier. But the modifier is specially for foreground styling. So you can check your condition inside of it.

e.g.

struct ForegroundModifier: ViewModifier{
    
    let color: Color
    
    func body(content: Content) -> some View {
        if #available(iOS 15.0, *){
            content.foregroundStyle(color)
        }else{
            content.foregroundColor(color)
        }
    }
}

extension View{
    func myForegroundStyle(_ color: Color) -> some View{
        modifier(ForegroundModifier(color: color))
    }
}

and apply it like:

struct TestView: View {
    var body: some View {
        Text("TestThis")
            .myForegroundStyle(.red)
    }
}
like image 42
burnsi Avatar answered Dec 22 '25 18:12

burnsi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!