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
Swift Pattern Matching with Enum and Optional Tuple Associated Values
Creating a Type Bound to a Certain Range in Swift
Uitextview Draw Invisible/Whitespace Characters
Scntext Alignment Not Working in iOS
How to Convert Data of Int16 Audio Samples to Array of Float Audio Samples
Using Vapor-Fluent to Upsert Models
How to Prevent a Spacer to Make a VStack Greedly Grow Beyond Necessary
How to Change Audio Pitch During Playback? (Swift 4)
Core Data: Rename Attribute Without Having Issues with Users and Their Current Data
Build Error in Xcode on Cloud-Hosted MAC on VSts
How to Test Asynchronous Methods Swift
How to Cast an @Binding in Swift
How to Make High Score of Game to Be Saved on Leaderboard, with Swift
Xctestcase Optional Instance Variable
How to Implement a Swift Protocol Across Structs with Conflicting Property Names
iOS Swift Error: 'T' Is Not Convertible to 'Mirrordisposition'