Experiencing a weird bug in SwiftUI in Xcode 11.6 / iOS 13.6 with the below code.
It will render two text fields with a white border around them (you can change to black border if you're not using Dark Mode). The bug is that the hit area of the tap gesture recognizer is not the same as the hit area of the SecureField. So you can tap on the edges of the field and although the recognizer fires, the actual text field does not become the first responder.
To illustrate this, I set the background color of both UITextFields (which SwiftUI uses under the hood) to green. To make a given UITextField "become the first responder," you must tap inside this green area, otherwise you cannot type into that field.
The problem is that because our app is to be cross-platform, i.e. it would run on AppKit or UIKit, we do not want to use any methods based on UIKit to handle how the UI works. We need to know which field the user is currently editing so we can set the border color of that field to green (as per design requirements of our UIX team). So, since we cannot set up delegates to listen on the normal UITextField delegate methods, we decided upon using tap gesture recognizers to determine when the user is editing a given field.
However now we're experiencing this issue where the areas of padding are included in the tapGestureRecognizer that we added in SwiftUI, but the underlying text field itself does not receive such a gesture unless it's in the smaller area inside the padding.
What is a solution to this that can be done purely in SwiftUI?
import PlaygroundSupport
import SwiftUI
import UIKit
public extension View {
var any: AnyView { AnyView(self) }
}
struct Value: Identifiable {
typealias ID = Int
let id: ID
var text: String = ""
}
struct MyView: View {
@State var fields: [Value] = [Value(id: 0), Value(id: 1)]
init() {
UITextField.appearance().backgroundColor = .green
}
var body: some View {
ForEach(fields) { field in
SecureField(
" ",
text: self.$fields[field.id].text,
onCommit: {
print("committed")
})
.onTapGesture {
print("tapped")
}
.padding(12)
.overlay(
RoundedRectangle(
cornerRadius: 5
).stroke(
Color.white,
lineWidth: 2
)
)
}
}
}