Dealing with stacked accessibility identifiers in SwiftUI - swift

This not exactly a code question but it's code related so I think those go hand-to-hand. I am using a tool that runs on top of Appium to do end to end tests but I'm struggling with accessibility identifiers.
Taking this view as an example:
#ViewBuilder private var footerButtons: some View {
HStack(spacing: Constants.padding16) {
BaseButton(text: Constants.backButtonTitle,
size: .medium,
form: .roundedRectangle,
type: .outline(.grey500),
action: {
action(.back)
})
.accessibilityIdentifier(AccessibilityIdentifiers.backButton)
BaseButton(text: Constants.pauseButtonTitle,
size: .medium,
form: .roundedRectangle,
type: .fill(.primary500),
action: {
action(.pause)
})
.accessibilityIdentifier(AccessibilityIdentifiers.pauseButton)
}
.padding(.vertical, Constants.padding8)
}
As of now, using XCTest, I am perfectly able to test with these identifiers, both pauseButton and backButton but, when using an Appium based tool, those no longer appear. This is incredibly frustrating and the only way to fix this is by adding a .accessibilityElement(children: .contain) at the end of the HStack.
This happens with a never ending amount of cases and I would really like to know why this is and if there's anything we can do to fix this other than adding that line of code or creating a generic view that works as a Stack but that already has that modifier applied to it.

Related

NavigationLinkError (from YT Video)

I Was following this tutorial (https://www.youtube.com/watch?v=GiCTgsH0dtk) and got this error anyone know a work around others in the comments having trouble with the same thing so i thought id help
Do you know the correct way to handle this new error for this piece of code?
NavigationLink(destination: SignUp(show: self.$show), isActive: self.$show) {
Text("")
}
.hidden()
Login(show: self.$show)
}
Error:
'init(destination:isActive:label:)' was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a NavigationStack or NavigationSplitView
First, change your NavigationLink to NavigationStack.
And lastly, where your - if you have one - .navigationTitle("") goes (this is where NavigationView closes), Xcode is asking you to add a .navigationDestination() as following:
.navigationDestination(isPresented: $show) {
//Whatever View you want to display...
}
This alert, not error, happens because of iOS 16 and Apple's constant changes on the Swift and Swift's frameworks changes.

Typing in TextField moves cursor to end (macOS)

In macOS Ventura 13.0.1 and Xcode 14.1, I'm experiencing an issue where when I type in the beginning of a TextField, the cursor for some reason moves to the back.
I was able to reproduce it very simply:
struct ContentView: View {
#State private var text = "DEFG"
var body: some View {
NavigationSplitView {
Text("Sidebar")
} detail: {
VStack {
TextField("Text", text: $text)
}
}
}
}
To reproduce:
Open the app, and move the cursor to the start of the TextField. (so the insertion point is before the "D".
Type a letter, like "A", and the insertion point should jump to the end for some reason.
I have determined the cause is the VStack. For some reason, removing it fixes this issue entirely. However, in my real app, I do need the VStack as I have other elements too.
I wonder what's going on here. Is there some major oversight I have made? Or could this be an issue with SwiftUI?
If anyone is having trouble reproducing, I can upload a video.

NavigationLink syntax

I'm trying to learn SwiftUI and Swift in general so I'm a total newbie here. I started by reading docs on Swift Language, making a console app and playing around with a bunch of concepts of the language there. Then I tried SwiftUI and immediately I see a bunch of syntax that wasn't documented in the language itself.
So I dug around some more and I see there is a bunch of compiler and language magic going on behind the scenes which makes the syntax I see in SwiftUI work. A lot of the magic maybe isn't so well documented. So I dug around and found answers to most of my questions about the SwiftUI syntax I'm seeing. Except this:
NavigationView{
VStack {
Text("Select your device")
List{
NavigationLink{
SensorView()
} label:{
Text("Raspberry Pi Zero")
}
}
}
What is with the label: statement outside of the curly braces for the NavigationLink closure all about? I can see in my app that it creates a label in the NavigationLink but I don't understand why the label: is outside of the curly braces where it looks to me to be more or less detached from the NavigationLink it is seemingly associated with? I'm trying to understand this so I will know when/where to apply this pattern. I copied the code above from someone else's sample.
Any insighgts or teachings would be appreciated.
This new syntax is part of Multiple Trailing Closures, which was released recently. Let's look at your NavigationLink initializer:
init(destination: () -> Destination, label: () -> Label)
Here, there's 2 parameters that take in closures: destination and label. So, that means you can write it like this (the plain, normal way):
NavigationLink(destination: {
Text("The destination")
}, label: {
Text("Click me!")
})
Or this, via trailing closure syntax:
NavigationLink(destination: {
Text("The destination")
}) {
Text("Click me!")
}
Or what you did in your question. Note: when you have multiple trailing closures, you need to add the argument label (for example label:) for all closures after the first.
NavigationLink {
Text("The destination")
} label: {
Text("Click me!")
}

Selecting a picker value to lead to a text field, SwiftUI

Im trying to implement a feature in my app.
When I click on my picker:
Picker(selection: $profileViewModel.education,
label: Text("Education Level")) {
ForEach(Education.levels, id: \.self) { level in
Text(level).tag(level)
}
}
This takes me to a screen and then I select the value (this is fine - it works as expected)
How could I select the value which then takes my to let's say another screen so I can fill in more details regarding the selected value.
For example the above picker has a values to select eduction level, after selecting it, how could I get an action sheet/another screen appear so I can have a text field there to save this extra data to or once the selection is made, a text field appears for me to save some extra data, and then clicking a button which would take me to the original screen of the picker (hope that makes sense)?
I've tried researching online for a problem similar to this but can't seem to find one/or if you can point me in the direction of what I should be looking into?.
Tried the following:
If I correctly understood your scenario here is a possible approach (replication tested with Xcode 12 / iOS 14)
Picker(selection: $profileViewModel.education,
label: Text("Education Level")) {
ForEach(Education.levels, id: \.self) { level in
Text(level).tag(level)
}
}
.onChange(of: profileViewModel.education) { _ in
DispatchQueue.main.async {
self.showSheet = true
}
}
.sheet(isPresented: $showSheet) {
// put here your text editor or anything
Text("Editor for \(profileViewModel.education)")
}

SwiftUI - NavigationView Error message - Argument passed to call that takes no arguments

I am trying to implement a really basic NavigationView in SwiftUI. When I try the sample code that I have seen on other websites it generates an error message in Xcode. I am not sure why or how to fix this.
I have tried to clean the project, quit Xcode-Beta and restart it but that did not work.
struct ContentView : View {
var body: some View {
NavigationView {
Text("This is a great app")
}
}
}
I thought the code above should work but the error I get says:
"Argument passed to call that takes no arguments."
Any ideas or suggestions?
VStack can only take 10 argument.
If more, there will be error, so you should make it nested.
from
VStack{
}
to
VStack{
VStack{
}
VStack{
}
}
I had this same error message too and figured out what I did wrong and then kind of felt like an idiot. Ha ha.
Take a look:
It took me a while to figure out that my struct was the same name as a previously defined struct VStack. Whoops!
So I'm wondering if you had a file in your project that did this too.
check-in your app is there any Swifui class with the name NavigationView.
also when you jump to the definition from NavigationView it should refer to:
#available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 7.0, *)
public struct NavigationView<Content> : View where Content : View {
public init(#ViewBuilder content: () -> Content)
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = Never
}
Testing Xcode 11.2.1 and it's still buggy. I noticed when I keep adding primitive views to my ContentView, I start getting errors like
"Argument passed to call that takes no arguments",
"Type of expression is ambiguous without more context" etc. on primitive views which worked before.
When I replaced, for example,
ScrollView {
VStack {
Text
Button
Image
Text
Button
Image
Text
Button
Image
...
}
}
with
ScrollView {
VStack {
VStack {
Text
Button
Image
}
VStack {
Text
Button
Image
}
VStack {
Text
Button
Image
}
...
}
my code started to compile and run again.
I found this problem when I accidentally try to redefine Text struct. Check if you naming your custom class the same as those in SwiftUI.
#Matteo Pacini helped me find the answer. When I started a new Xcode Project just to test the code above everything worked. I had a lot of files and was testing a lot of different code while experimenting with SwiftUI in my other project and for some reason XCode was always generating this error.
When I tried everything in a new project it worked. Something to be aware of while testing. Hope this helps others avoid similar problems.
Embed the 'Text("This is a great app")' in a VStack
struct ContentView : View {
var body: some View {
NavigationView {
Stack {
Text("This is a great app")
}
}
}
}