Swiftui: Using View Modifiers Between Different iOS Versions Without #Available

How to use view modifiers only available for iOS 14+ with deployment target of iOS 13

Mark body as @ViewBuilder - this will allow track internal different return types automatically, and remove return because explicit return disables view builder wrapper.

So here is fixed variant

struct CompatibleTextCaseModifier: ViewModifier {

@ViewBuilder
func body(content: Content) -> some View {
if #available(iOS 14.0, *) {
content
.textCase(.none)
} else {
content
}
}
}

and usage

Section(header:
Text("Header")
.modifier(CompatibleTextCaseModifier())
.font(.system(size: 14, weight: .bold))
.foregroundColor(.secondary)
.padding(.top, 50)
) {
Text("test")
}

In SwiftUI, is it possible to use a modifier only for a certain os target?

your better off doing this:

 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
}

iOS 16 View Modifier not consistent across List headers

Set the .listStyle so you have consistency

Because Apple can decide what .listStyle is best, it has changed with every version of SwiftUI for different settings.

If you set it, then it takes your preference not Apple's preference for the circumstance.

The photos you show are .plain for the sidebar and .grouped for the detail.

How to use `.backgroundTask` modifier while still targeting iOS 15?

We cannot use condition right in scene body, because SceneBuilder does not support conditional expression, so a solution is to have completely different apps loaded depending on availability.

Simplified code to have less lines:

struct AppScene: Scene {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

@available(iOS 16, *)
struct RefreshingAppScene: Scene {
var body: some Scene {
WindowGroup {
ContentView()
}
.backgroundTask(.appRefresh("refreshAllData")) {
refreshAllData()
}
}
}

@main
struct AppLoader {
static func main() {
if #available(iOS 16, *) { // << conditional availability !!
New_iOSApp.main()
} else {
Old_iOSApp.main()
}
}
}

@available (iOS 16, *)
struct New_iOSApp: App {
var body: some Scene {
RefreshingAppScene()
}
}

struct Old_iOSApp: App {
var body: some Scene {
AppScene()
}
}

Tested with Xcode 14b3 / iOS 16



Related Topics



Leave a reply



Submit