skip to Main Content

Im 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 thing I learned is to not repeat the same code but how can I apply different modifiers easily without repeating the code? some thing 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 Im 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

2

Answers


  1. 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)
        }
    }
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search