SwiftUI NavigationView/Stack if available iOS 15/16 - xcode

There's something I don't really understand about the transition from NavigationView to NavigationStack for SwiftUI 4 and iOS 16.
I have 2 applications running on the App Store (targeting iOS 15 and above) and of course I'm using NavigationView. This weekend, I was looking for a solution to have them ready for iOS 16 by replacing:
var body: some View {
NavigationView {
ScrollView { /* code here */ }
}
}
To something like this:
var body: some View {
if #available(iOS 16, *) {
NavigationStack {
} else {
NavigationView {
}
ScrollView { /* code here */ }
}
}
But finally, before doing so, I tried them with iOS 16 Beta and they're perfectly fine.
I don't understand, I thought it would be total a mess but finally no. Do you have an explanation? Maybe, deprecated isn't what it should mean?

NavigationView is deprecated, not obsoleted. When a component becomes deprecated, it still can be used until Apple decides to obsolete it which will cause a crash when used. Although it's functional, you shouldn't use it.

Related

XCode Preview with Color Loop for SwiftUI Previews not working anymore

Before XCode 14, the following syntax was working well to loop through the different color schemes.
static var previews: some View {
ForEach(ColorScheme.allCases, id: \.self) {
MyView()
.preferredColorScheme($0)
}
}
Starting XCode 14, this results in
PreviewUpdateTimedOutError: Updating took more than 5 seconds
I suspect, this has to do with the new button in XCode to display the Color Scheme Variants in Preview now, but i rather like the old behaviour back.
Any ideas how to do that?

SwiftUI View with TextField and SecureField buggy on macOS (shows strange view)

On macOS I need a SwiftUI form that has a TextField (for email) and then a SecureField (for password). Seems simple, but when I start typing in the TextField a strange view appears below the field:
Some observations:
This does not happen if the SecureField is replaced by a TextField.
This does not happen if the TextField is removed.
A similar strange view will also appear when I start to type in the SecureField.
The strange views will disappear and reappear as I change focus between the fields.
Finally, this does not happen if the SecureField is placed before the TextField (maybe I should start a new trend in UI design;-).
Can somebody suggest a way to avoid or work around this issue? Here is the code (simplified as much as possible):
import SwiftUI
struct ContentView: View {
#State var emailAddress : String = ""
#State var password : String = ""
var body: some View {
Group {
TextField("Email:", text: $emailAddress)
SecureField("Password:", text: $password, prompt: nil)
}
.padding()
Spacer()
}
}
Xcode 13.4.1; macOS 12.5; MacBook Pro (2020). Also happened with Xcode 13.4 and macOS 12.4.x.
Update 2022.08.13:
Per request from Multi Media here is a screenshot with strange view that appears when typing in the SecureField. Here I've added an additional TextField, as suggested (although not with zero height, so that it is visible in the screenshot).
Also I should note that you can make the strange view disappear, e.g. by pressing the ESC key.
Had this same problem on macos 12.5.1, without changing anything else, I installed macos 13 beta 6, and the bug was fixed. It appears to be an odd interaction between SecureField and either TextField or TextEditor on macos 12.
I found how to solve the problem,just add focusable() to the secureField,you can try,it works for me!
I don't know the reason why this is happening (maybe it should give you suggestions like the SecureField), but apparently this is not the case when you have the same TextField above the real one.
This isn't perfect, since there is minimal Space on the top, but it works and is better than the strange window:
import SwiftUI
struct ContentView: View {
#State var emailAddress : String = ""
#State var password : String = ""
var body: some View {
VStack {
TextField("Email:", text: $emailAddress)
.frame(width: 0, height: 0)
TextField("Email:", text: $emailAddress)
SecureField("Password:", text: $password, prompt: nil)
}
.padding()
Spacer()
}
}
I have tested it with Xcode 14 beta 3 and my MacBook Pro M1.

Fail to preview Widget in Xcode with SwiftUI Preview

I am trying to preview some View by using Widget context, like:
struct MyTasksView_Previews: PreviewProvider {
static var previews: some View {
MyTasksView(
myTasks: Fake.myTasks,
user: Fake.user,
error: ""
)
.previewContext(WidgetPreviewContext(family: .systemMedium))
}
}
However, I'm getting this error while attempt to run the preview. And, I'm not sure why it is happing.
RemoteHumanReadableError: Unknown preview provider “MyTasksView_Previews”
MyApp does not contain a preview provider named “MyTasksView_Previews”. Check your build settings to ensure the preview provider is compiled into your product.
I, also, tried to use a simple Text(text).previewContext(WidgetPreviewContext(family: .systemMedium)), but it did not work either. I'm using the Xcode beta 5.
In Apple Emoji Rangers Demo App for WWDC 2020. We can see this piece of code for preview:
struct CharacterNameView_Previews: PreviewProvider {
static var previews: some View {
CharacterNameView(CharacterDetail.panda)
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
I had the similar issue and I solved it by putting the View inside a VStack (or another container).
Here is my code that worked:
struct WidgetViewPreviews: PreviewProvider {
static var previews: some View {
VStack {
WidgetView(entry: .mock)
}
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
It's a bug in Xcode, you can only use previewContext of "single" Widgets Target.
So you need to unselect other Targets.
I had the same problem when adding widgets extension to my UIKit app.
Changing the Class target membership to widget extension solved this for me.
Add Widget extension target, and activate it. For more information
https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension

Accessing system colors in WatchKit

I am trying to use UIKit colors for my Apple Watch interface. You can do it in iOS with UIColor class properties like .systemBackground and others. For example:
let myColor = UIColor.systemBlue
Gives me error when compiling watchOS extension target:
Type 'UIColor' has no member 'UIColor.systemBlue'.
I wonder tis there alternative way to get this system colors, and if not — what I need is to get a color of some UI elements, like SwiftUI table view row background which looks very similar to UIColor.systemGray5.
#State private var isActive = false
var body: some View {
List {
Section() {
ForEach(self.dataSource) { item in
CustomCell()
.listRowPlatterColor(self.isActive ? Color(UIColor.systemGray5) : Color(.orange))
}
}
}
}
Code above won't compile because UIColor.systemGray5 is not found in WatchKit. I have tried to create a class which is sued both in iPhone and Watch target and it fixes Xcode autocompletion. But the app breaks when trying to use it the Apple Watch target.
I hope there's a way rather then finding correct color and hard-coding it.
Looking at the documentation, the UIColor.system-ish are only available for iOS, Catalyst and some for tvOS. What you can do is extend UIColor and create you systemGray5:
extension UIColor {
static var mySystemGray5: UIColor {
return .init(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
}
}
And use on your code like:
ForEach(self.dataSource) { item in
CustomCell()
.listRowPlatterColor(self.isActive ? Color(UIColor.mySystemGray5) : Color(.orange))
}
Since you are using SwiftUI, Color.blue is equivalent to UIColor.systemBlue.
Unfortunately, Color doesn't have a lots of UIColor system colors, hopefully Apple add missing colors on WWDC 2020.
May be use can use something like Color.gray.opacity.opacity(0.25) in the meanwhile?

How can I resolve this Xcode OptimizationLevelError error while previewing simple swiftui code in canvas?

I've been successful using SwiftUI for a few months with very little Xcode experience. I'm trying to add some simple help screens that I would like to preview in the SwiftUI canvas. However, I'm receiving the following error:
OptimizationLevelError: not building -Onone
The message is shown when pressing the "diagnostics" button. Problem persists after pressing "try again" button.
Xcode: Version 11.3 (11C29)
Catalina: 10.15.2 (19C57)
The code could not be simpler:
import SwiftUI
struct HelpSortView: View {
var body: some View {
VStack {
Text("You can sort the list by Name, Sail Number, Class, or Favorites.")
.lineLimit(10)
VStack(alignment: .center) {
Image("help-sort")
}
}
}
}
struct HelpSortView_Previews: PreviewProvider {
static var previews: some View {
HelpSortView()
}
}
It turns out that I had my Xcode scheme, Build Configuration set to Release instead of debug. In Xcode, select Product, Scheme, Edit Scheme, Run (on left side), Info tab, Build Configuration, set drop-down to Debug.

Resources