SwiftUI iOS 14 beta TextField 100% CPU - swiftui

Using iOS 14 and Xcode 12.0 beta 6 if I try and use a simple TextField anywhere
import SwiftUI
struct ContentView: View {
#State private var name: String = "Tim"
var body: some View {
VStack {
TextField("Enter your name", text: $name)
Text("Hello, \(name)!")
}
}
}
the keyboard opens but then the CPU goes to 99%/100% and app is frozen.
Is this a known issue? How do I fix it?

This bug exists since the 14.0 betas and has not been fixed so far :/ I tried to search for workarounds or solutions but there seems to be none at the moment.
Once the user activates an input field, the CPU goes to 95%-100% and stays there until you actually quit the app.

I found some reason, If you use some .onAppear listener, When device keyboard is opened, application is being crazy if you set or change any #EnvironmentObject variable using .onAppear listener anywhere on your app. But it is not for all .onAppear... it was really weird. I searched piece by piece those when I have noticed.

Related

SwiftUI, Alert disrupts NavigationLink?

previous threads on this question have non-swift answers that I can't figure out how to implement in SwiftUI. Please note that I'm using Xcode 12.5.
I created a playground in an attempt to post a "demo" version of the code, but wouldn't you know it, the playground runs flawlessly. So, going to post little bits of the code without making your eyes bleed. I'm getting this warning:
pushViewController:animated: called on <TtGC7SwiftUI41StyleContextSplitViewNavigationControllerVS_19SidebarStyleContext 0x103021c00> while an existing transition or presentation is occurring; the navigation stack will not be updated.
Here's how the code operates:
Navigate from View A to View B. In View A's NavigationLink, I run this:
NavigationLink(destination: MainScreen(user: user)) {
CapsuleButtonView(txt: "LOGIN")
}.simultaneousGesture(TapGesture().onEnded {
user.login()
})
.padding([.leading, .bottom, .trailing])
user.login() checks to see if the username and password are entered (bindings). If not, it flips a #Published Bool which the view that runs the above code uses to trigger the alert message:
.alert(isPresented: $user.alert, content: {
Alert(title: Text("Message"), message: Text(user.alertMsg), dismissButton: .destructive(Text("Ok")))
})
The Alert pops as it should, but I think it does it after the NavigationLink has started to navigate away from View A to View B. So, after the Alert pops, the NavigationLink's simultaneousGesture block still runs the code in it (I checked with print statement), but does NOT navigate to View B.
Thanks for your help guys. After 3 days of looking a this, I'm about to tear out what little hair I have left.
Try adding navigationViewStyle(.stack)
NavigationView {
//Your view
}
.navigationViewStyle(.stack)

NavigationView only shows Back button in SwiftUI

I just create a swiftUI project and type this code on CntentView.swift. But the result is this image below. It was the same when I tried to run it on a real machine.
Why?
Environment:
Xcode Version 12.2(12B45b),
This is code of "Test13App.swift". Not edited any line.
Thank you very much for your comments. Since I only have iPad pro (and not have iPhone), I just knew this is a default behaviour of iPad split view now by your comments. Adding .navigationViewStyle(DefaultNavigationViewStyle()) right after NavigationView solved the problem like this
SwiftUI NavigationView on the iPad Pro
Sorry and Thanks very much!
If you want to change the style of your NavigationView on iPad making it similar to iPhone, you could use the:
.navigationViewStyle(StackNavigationViewStyle())
option in your NavigationView.
Like this:
struct ContentView: View {
var body: some View {
NavigationView{
Text("prova")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
When focused on both iPhone and iPad devices some developer's missing set the navigationview style type.
Set the NavigationView Style

SwiftUI SecureField: How to achieve the same character obscuring behaviour as in UIKit?

My problem is SecureField in SwiftUI doesn’t display characters input by the user for any time at all, it just directly shows the '•' symbol for each character as it's typed - whereas in UIKit, UITextField (with isSecureTextEntry = true) shows the latest character for a second before hiding it behind '•'.
UX testers at my company have requested I bring back the "old behaviour" - but this behaviour doesn't seem part of any public API.
Interestingly this goes for UITextField custom classes injected into SwiftUI using UIViewRepresentable too - they behave in the "SwiftUI way" described above. So there's some contextual behaviour modification going on in SwiftUI for all secure UITextField behaviour? I'd have to completely rewrite my SwiftUI form into a full UIViewController to get back the behaviour (modally pushed UIViewControllers with secure UITextFields do exhibit the desired behaviour.)
Is this a sort of sideline bug in SwiftUI? I see the same thing for SwiftUI in both iOS13 and 14. Anyone seen a workaround or solution?
-EDIT-
After #Asperi's great explanation below, I noticed that my UITextField custom classes injected into SwiftUI using UIViewRepresentable were forcing this behaviour by unnecessarily setting the text binding in the updateUIView call. Using a Coordinator only to deal with text logic fixed the problem for me when using this method.
The observed effect is due to immediate apply to bound string state and immediate react/rebuild of view.
To bring desired behavior beck we need to postpone somehow state update and thus give a chance for SecuredField/UITextField to update self without synchronisation with state.
Here is a demo of possible direction (it is not ideal, but a way to go). Tested with Xcode 12.1 / iOS 14.1.
struct DemoSecureFieldView: View {
#State private var password = "demo"
var textBinding: Binding<String> {
Binding(get: { password },
set: { value in
// more logic can be added to delay _only_ if new symbol added,
// and force apply if next symbol came fast
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
password = value
}
}
)
}
var body: some View {
VStack {
SecureField("Placeholder", text: textBinding)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}.background(Color.pink)
}
}

iOS 14 AssistiveTouch Dwell Control sometimes not working on SwiftUI Buttons

I have a SwiftUI App which uses regular Button views and our customers use AssistiveTouch's DwellControl feature quite often. On iOS 13 DwellControl was working fine but on iOS 14 beta 8 DwellControl fails to be able click on those buttons.
The Buttons can be tapped by finger and clicked with the normal mouse but not with the DwellControl feature.
I have tried adding accessibility traits like isButton, but nothing works.
Has anyone encountered the same problem and has a solution or any insight at all? I know this is quite niche but any help is appreciated!
EDIT:
I have tested it with a very simple example, including one a Button and it works fine. It seems to be a side effect of some sorts in my specific App.
I have several ZStacks which show and hide some views like modals and popovers. Could this be the source of failure?
What I don't get is that the Buttons can be tapped and clicked... If a view was blocking the Button then this shouldn't be possible right?
I have tried Release and Debug builds which does not make a difference.
When DwellControl is activated and the cursor is on the Button that shall be clicked, tapping doesn't work either. But when the cursor is nowhere near the Button, tapping works fine.
I have send a report via Feedback to Apple.
EDIT:
I found the cause. ScrollView somehow prevents all DwellControl clicks from happening. That happens whenever a ScrollView is somewhere present in one of the Views.
Minimal example:
struct ContentView: View {
#State var show = false
var body: some View {
ZStack {
ScrollView {
Button(action: {
print("This should be printed but isn't....")
}, label: {
Text("Button in ScrollView")
})
}
}
}
}
I know its niche but maybe someone needs this.
There are other components which are affected and cause the same behaviour:
ScrollView
TextField
Slider
Stepper
UIViewRepresentable
For me this is a big issue, since our customers use DwellControl quite often.
EDIT:
This can be replicated in the newest iOS 14.2 beta 1:
import SwiftUI
#main
struct TempSwitUIApp: App {
#State private var text: String = "I am a text"
var body: some Scene {
WindowGroup {
Button(action: {
print("\(UUID()) \(self.text)")
}, label: {
Text("Print text to the console")
})
TextField("Hello", text: self.$text)
}
}
}
I updated my issue with Apple but haven't heard from them yet.

What is the equivalent of WKInterfaceController.didAppear() in SwiftUI on watchOS?

I'm building an Apple Watch app, and there is code I want to run every time the app is brought to the foreground.
Previously, if I wanted to do this in a watchOS with a WKInterfaceController, I would put this code in didAppear().
In SwiftUI, there is onAppear(), but when I call that on watchOS it only seems to be called the first time the app loads up, so it behaves like WKInterfaceController.willActivate() instead. The app has just a single view.
If onAppear() is the equivalent of WKInterfaceController.willActivate(), is there a different SwiftUI function that is the equivalent of WKInterfaceController.didAppear()?
Here's my current example code:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello World").font(.footnote)
.onAppear {
print("onAppear called")
}
}
}
In the meantime, I am going to experiment with triggering what I need to do within the ExtensionDelegate, but I'm just trying to learn my way around SwiftUI on WatchOS, so knowing the answer to this would be helpful in the future.