GarySabo
GarySabo

Reputation: 6690

How to wrap #available in this custom .if extension on a SwiftUI View?

I'm using this .if extension which works great and should be added to SwiftUI, however it won't work in this case to check #available because #available may only be used as condition of an 'if', 'guard' or 'while' statement How can I make it work with this .if, anyway?

    //Does not compile for #available may only be used as condition of an 'if', 'guard' or 'while' statement
   ForEach...
   .if(#available(iOS 15.0, *)) { $0.refreshable {
                        
                    } }

extension View {
  @ViewBuilder
  func `if`<Transform: View>(
    _ condition: Bool,
    transform: (Self) -> Transform
  ) -> some View {
    if condition {
      transform(self)
    } else {
      self
    }
  }
}

Upvotes: 1

Views: 838

Answers (2)

efremidze
efremidze

Reputation: 2862

You can add an extension to View that is a @ViewBuilder modifier that accepts conditionals.

extension View {
    @ViewBuilder
    func modify(@ViewBuilder _ transform: (Self) -> (some View)?) -> some View {
        if let view = transform(self) {
            view
        } else {
            self
        }
    }
}

Example:

struct ContentView: View {
    var body: some View {
        List {
            Text("Hello")
            /* More list items... */
        }
        .modify {
             if #available(iOS 15.0, *) {
                 $0.refreshable {
                     //
                 }
             }
        }
    }
}

Upvotes: 1

George
George

Reputation: 30401

I would typically just do .if(true) and then check availability inside the closure. Unfortunately, we can't check for availability in the if modifier.

Example:

struct ContentView: View {
    var body: some View {
        List {
            Text("Hello")
            /* More list items... */
        }
        .if(true) {
            if #available(iOS 15, *) {
                $0.refreshable {
                    //
                }
            } else {
                $0
            }
        }
    }
}

Added @ViewBuilder to transform parameter so you can return different View types in the if:

extension View {
    @ViewBuilder func `if`<Transform: View>(_ condition: Bool, @ViewBuilder transform: (Self) -> Transform) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}

Upvotes: 4

Related Questions