SwiftUI dragging an object lags on newer iPhones - ios

I have this really simple code for dragging an object on the screen:
struct ContentView: View {
#GestureState var translation = CGSize.zero
var body: some View {
Rectangle()
.frame(width: 200, height: 200)
.offset(translation)
.gesture(
DragGesture().updating($translation, body: { value, state, transaction in
state = value.translation
})
)
}}
When testing on device, it works perfectly smooth on an older model (iPhone 7 Plus), but it's kind of laggy on newer ones (iPhone 13 mini and iPhone 13). On simulators I could not reproduce it, only on a real device. Is there something I'm missing?
iphone13Mini
iphone 7Plus
The difference is only slightly seen on the videos, but in real life the lag feels more somehow on the 13.

Related

SwiftUI different behavior on different iOS versions

I have been developing an app with minimum iOS 13, but whole development process was done on iOS 15. Now when testing the iOS 13 devices, I noticed some problems.
Minimalistic example: You have a list of items, where each item contains leading icon, with a title and a subtitle vertically stacked. To adapt to various screen sizes, I attached a .minimumScaleFactor() to the texts so they would scale down when needed. That's working nicely on iOS 15. After a whole lot of testing, it also works on iOS 13.4 that is the oldest where I've got it working, so, iOS 13 - <13.4 is in question here.
On the screenshot you can see iPhone 8 13.3 vs iPhone 8 13.4, the text is scaled down even when there is space available. On iPhone 6s Plus 13.3 there is even more available space (screen size).
And the code:
struct Viewwww: View {
var title = "This is a title This is a title This is a title This is a title This is a title "
var subtitle = "This is a subtitle This is a subtitle This is a subtitle This is a subtitle This is a subtitle "
var body: some View {
VStack{
Text("Onboarding test").font(.title).multilineTextAlignment(.center).lineLimit(2)
Spacer()
buildItem()
buildItem()
buildItem()
buildItem()
buildItem()
Spacer()
}.padding(.horizontal, 20)
.padding(.top, 30)
}
#ViewBuilder
func buildItem() -> some View {
HStack(alignment: .top, spacing: 20){
VStack {
Image(systemName: "pin").resizable().scaledToFit().frame(width: 44, height: 44)
}
VStack(alignment: .leading, spacing: 10){
Text(title).font(Font.title).minimumScaleFactor(0.5)
Text(subtitle).font(Font.body).minimumScaleFactor(0.5)
}
Spacer()
}.frame(maxWidth: .infinity).background(Color.red)
}
}
So anyone has experienced this, and can help? Thank you!

iOS15 bug? Overlapping touch ares on iPhone screens with some HStack()ed Picker() objects

Hello developers!
I encountered a situation, where I like to get some feedback from experienced Swift developers at the pulse of time.
For an iOS app I need some user inputs, three to be precise. These can be seen as a whole number in the current state. So I thought, to put them in an integer variable. I decided to use Swift as the language and SwiftUI for the Interface.
Table of contents:
Story
Situation (Problem)
Question
Hardware
Example Code
THE STORY (in short):
I tried to find a way to get the user input into the variable. TextField() handles String. On TextFields()s tap some screen keyboard appears. After input the user can hit the 'return' button and the keyboard disappears. My goal was intercept all characters that did not belong to an integer. So I added a filter function which only allowed numbers from 0 to 9. Fine, but at the default keyboard the user had to hit the symbols button to get a number pad provided.
So I picked a 'Number Pad'. That one has, despite the unpopulated space, no 'return' button. Further the keyboard blocks the view to the Interface. Well, perhaps implementing something like IQKeyboardManager from 'Iftekhar Qurashi' (see: https://cocoapods.org/pods/IQKeyboardManager) can counter the insufficiency, But I asked myself, if such a basic task requires an external library. There should be a native way, right?
THE SITUATION:
After the described and discarded idea, I looked around a went for some Picker()s, which went well... visually. If you grab a picker wheel which has a neighbor to right, you will move the right neighbors wheel. This is shown is a video (just below 'Step 4:'): https://blckbirds.com/post/swiftui-how-to-create-a-multi-component-picker/
Same on the physical devices when in portrait mode(iPhone 6S, X and 13). Landscape offers enough space.
The suggested method to cure the unwanted behavior, namely to add '.compositingGroup().clipped()' to the end of each Picker()s closure does not work for me (iOS 15). As mentioned in the comments by 'Dave Reed', the fact, that the pickers work fine on my Intel MacBooks Xcode (preview and simulators) could be that im running currently 13.1. over there.
For the screenshot I commented the 'compositingGroup().clipped()' lines as shown in the example code. There are two gray color shades, where I think the touch area is (roughly?) positioned. The same can be said if 'compositingGroup().clipped()' are active at position 1.1 and 2.1 (see comment). If 'compositingGroup().clipped()' get active at position 1.2 and 2.2 the gray bars get cut but the touch area is still wide and overlaps the left neighbor.
See some screenshots:
iPhone13portrait
iPhone13landscape
THE QUESTION:
Is there a way of cutting or stretching the touch area for a Picker() object to fit its current stack?
Are there any ideas of using a number only keyboard with a return button?
THE HARDWARE:
Development Platforms:
MacBook Pro (Retina 13", Early 2015, Dual-Core Intel Core i5), FINE ON SIMULATORs AND PREVIEW (Canvas)(iPhone8, 13), Xcode 13.1
MacBook Pro (16", 2021, Apple M1 Pro), Situation occurs on simulators and Preview (Canvas)(iPhone8, 13), Xcode: now 13.2.1
Hardware Test Devices:
iPhone 6s, iOS Version: 15.2, Situation occurs
iPhone X, iOS Version: 15.2, Situation occurs
iPhone 13, iOS Version: 15.1.1, Situation occurs
THE FULL EXAMPLE CODE (incl. Preview):
// demonstration file for bad multiple picker touch area overlay
import SwiftUI
struct ContentView: View {
#State var rice: Int = 51
#State var corn: Int = 20
let range: ClosedRange<Int> = 0...99
var body: some View {
VStack{
HStack(alignment: .center, spacing: 0){
Spacer()
VStack(){//picker 1
Text("rice")
VStack(){
Picker("", selection: $rice) {
ForEach(range, id: \.self){ Text("\($0)").tag($0) }
}
//POSITION 1.1
.pickerStyle(.wheel)
//.compositingGroup()
//.clipped(antialiased: true)
}
//POSITION 1.2
.frame(width: 40, height: 100)
//.compositingGroup()
//.clipped(antialiased: true)
.border(Color.red)
}
Spacer()
VStack(){//picker 2
Text("corn")
VStack(){
Picker("", selection: $corn) {
ForEach(range, id: \.self){ Text("\($0)").tag($0) }
}
//POSITION 1.2
.pickerStyle(.wheel)
//.compositingGroup()
//.clipped(antialiased: true)
}
//POSITION 2.2
.frame(width: 40, height: 100)
//.compositingGroup()
//.clipped(antialiased: true)
.border(Color(UIColor.secondaryLabel))
}
Spacer()
}// End of HStack
.padding()
}.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 2)
).padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

SwiftUI Eye Tracking: Eye tracking performance is slow but on device rotation runs smoothly

I have recently started to code on SwiftUI with no knowledge or experience in Application programming.
I have a simple eye gaze tracking app using this Framework:
https://github.com/ukitomato/EyeTrackKit
Using the given examples i have this code running:
struct ContentView: View {
#ObservedObject var eyeTrackController: EyeTrackController = EyeTrackController(device: Device(type: .iPad), smoothingRange: 10, blinkThreshold: .infinity, isHidden: true)
var body: some View {
ZStack(alignment: .topLeading) {
eyeTrackController.view
Circle()
.fill(Color.blue.opacity(0.5))
.frame(width: 25, height: 25)
.position(x: eyeTrackController.eyeTrack.lookAtPoint.x, y: eyeTrackController.eyeTrack.lookAtPoint.y)
}.edgesIgnoringSafeArea(.all)
}
On launch while having the circle it barely moves, updating its position once every 3-5 seconds.
After rotating the device to landscape mode, then immediately rotating back to Portrait mode, the app seems to run perfectly fine, having no stutter and smooth transition between point to point.
Any idea what can cause this issue?
Thanks in advance!
After a while i found a solution for this problem:
On the line:
#ObservedObject var eyeTrackController: EyeTrackController = EyeTrackController(device: Device(type: .iPad), smoothingRange: 10, blinkThreshold: .infinity, isHidden: true)
The IsHidden value should be false instead of true
Don't know why excatly, but now the code runs smoothly

Keyboard safe area wrong for iPad in multitasking Slide Over (SwiftUI/UIKit)

I've got a view with content on the bottom edge, which gets partially obscured by the keyboard when the app is in Slide Over. This isn't the case in side-by-side multitasking or when the app is full screen.
All other configurations are fine:
Side-by-side, with keyboard:
Slide over, without keyboard:
Here's the example view code:
struct ContentView: View {
#State private var text = ""
var body: some View {
VStack {
TextField("", text: $text)
.textFieldStyle(RoundedBorderTextFieldStyle())
Spacer()
Text("Hello, world!")
.font(.title)
}
}
}
I've noticed this issue in SwiftUI lifecycle apps, UIKit lifecycle apps, across different iOS versions (including iOS 14) and on all iPad sizes.
I've seen solutions that check the UIDevice.current.userInterfaceIdiom and the window bounds to check if the app is in Slide Over and adjust the UI, but I'm using SwiftUI and I'd like to avoid this kind of hack. Any advice on how to deal with this?

iOS app blank navigationView opening screen on some device simulators and not others

I've written an app in Swift 5 using XCode 12.2
The app and all it's functionalities work on the following simulators: iPhone 8, iPhone SE 2nd Gen, iPhone 11 Pro, iPhone 12, iPhone 12 Pro, and iPhone 12 Mini
The issue occurs on all iPads, iPhone 8 plus, iPhone 11, iPhone 11 Pro Max, and iPhone 12 Pro Max.
I'm not sure what to make of this and am considering submitting a bug report/TSI, but I wanted to make sure there wasn't an obvious issue with my design.
Below is the structure of my content view. I removed things I though were extraneous to try to concisely illustrate the structure. I've also attached images of the properly running initial view vs the failing one.Proper Opening Screen, Problem opening Screen. I also ran it on a real iPhone SE 2nd gen and iPhone 8 and got the same results.
Thanks in advance.
struct ContentView: View {
//#State vars
var body: some View {
NavigationView{
ZStack{
Image("image")
VStack{
Spacer()
HStack{
Text("text")
.bold()
.foregroundColor(.white)
.font(.largeTitle)
Image("image2")
}.offset(y:10)
Form {
Section(header: Text("INITILIZATION SETTINGS")){
TextField("t1", text: $t1)
TextField("t2", text: $t2)
Stepper(value: $s1, in: 1...240){
Text("s1: \(s1)").onChange(of: s1, perform: { value in
playSound(sound: "sound1", volume: 0.3)
})
}
}
}.frame(minWidth: 0, idealWidth: 400, maxWidth:400, minHeight: 0, idealHeight: 100, maxHeight: 180, alignment: .center).border(Color.black, width: 7)
VStack()
{
NavigationLink(destination: otherView().onAppear{playSound(sound: "sound2")}, label: {
Text("label")
}).padding().background(Color.white).border(Color.black, width: 2).cornerRadius(3.0)
NavigationLink(destination: otherView2()) {
Text("label2").padding(5).background(Color.white).border(Color.black, width: 2).cornerRadius(3.0).offset(y:-5)
}
}
Spacer()
}
}
}.navigationBarTitle("").navigationBarHidden(true)
}
}
The solution was very simple and a matter of settings. Answer at ~29 mins in this Hacking With Swift video [https://youtu.be/nA6Jo6YnL9g?t=1720][1].
Large screen iOS devices automatically split the screen into multiple views with default navigationView{} settings. I don't know what the blank screen was about, but this fixed the problem
Simply add view modifier .navigationViewStyle(StackNavigationViewStyle())
I figured I'd self-answer instead of deleting the post because I had a lot of trouble finding solutions on the web! Hopefully this will be helpful to someone!

Resources