I am trying to apply the code in the accepted answer to this question, on how to make a SwiftUI TextField become a first responder. Here is the code, copied from that answer, which I tried to use in xcode:
struct CustomTextField: UIViewRepresentable {
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
var didBecomeFirstResponder = false
init(text: Binding<String>) {
_text = text
}
func textFieldDidChangeSelection(_ textField: UITextField) {
text = textField.text ?? ""
}
}
@Binding var text: String
var isFirstResponder: Bool = false
func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
return textField
}
func makeCoordinator() -> CustomTextField.Coordinator {
return Coordinator(text: $text)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
uiView.text = text
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
uiView.becomeFirstResponder()
context.coordinator.didBecomeFirstResponder = true
}
}
}
Running that code, however, gives me a run-time error, saying 'Unable to simultaneously satisfy constraints.' The error is shown below.
in makeUIView
in updateUIView in onEditingChanged 2020-08-14 16:02:48.445045-0600 OpenRussian[2965:122005] [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x600002580d20 'assistantHeight' TUISystemInputAssistantView:0x7fde585064a0.height == 44 (active)>", "<NSLayoutConstraint:0x600002591b30 'assistantView.bottom' TUISystemInputAssistantView:0x7fde585064a0.bottom == _UIKBCompatInputView:0x7fde51b78c50.top (active)>", "<NSLayoutConstraint:0x600002591ae0 'assistantView.top' V:|-(0)-[TUISystemInputAssistantView:0x7fde585064a0] (active, names: '|':UIInputSetHostView:0x7fde58518070 )>", "<NSLayoutConstraint:0x600002591720 'inputView.top' V:|-(0)-[_UIKBCompatInputView:0x7fde51b78c50] (active, names: '|':UIInputSetHostView:0x7fde58518070 )>" )
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x600002591b30 'assistantView.bottom' TUISystemInputAssistantView:0x7fde585064a0.bottom == _UIKBCompatInputView:0x7fde51b78c50.top (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
What can I modify to make this work, and avoid this 'unable to simultaneously satisfy constraints' run-time error?
Let's look at these one by one:
<NSLayoutConstraint:0x600002580d20 'assistantHeight' TUISystemInputAssistantView:0x7fde585064a0.height == 44 (active)>
This is saying view 0x7fde585064a0 is active and has 44 points height
<NSLayoutConstraint:0x600002591ae0 'assistantView.top' V:|-(0)-[TUISystemInputAssistantView:0x7fde585064a0] (active, names: '|':UIInputSetHostView:0x7fde58518070 )>
This is saying that 0x7fde585064a0's top edge must be a gap of 0 points from the top of its superview 0x7fde58518070
<NSLayoutConstraint:0x600002591b30 'assistantView.bottom' TUISystemInputAssistantView:0x7fde585064a0.bottom == _UIKBCompatInputView:0x7fde51b78c50.top (active)>
This is saying view 0x7fde51b78c50 and 0x7fde585064a0 are conflicting. These four things can't all be true. And the problem with constraints 0x600002591b30. Find out where the problem is and set true constraint.
I think it's useful to know the basics and understand what Apple / Xcode is trying to tell you via logs:
H = Horizontal constraint(for leading and Trailing)
V = Vertical constraint(top and bottom edge)
h = height
w = width
TopEdge -> V:|-(points)-[VIEW:memoryAddress]
BottomEdge -> V:[VIEW:memoryAddress]-(points)-|
Leading -> H:|-(points)-[VIEW:memoryAddress]
Trailing -> H:[VIEW:memoryAddress] -(points)-|
height -> h= --& v=--& V:[VIEW:memoryAddress((points)]
width -> VIEW:memoryAddress.width == points
between -> H:[VIEW 1]-(51)-[VIEW 2]
Try a bit corrected variant provided below (with testing view). Tested with Xcode 12 / iOS 14 - no console warnings observed.
struct CustomTextField: UIViewRepresentable {
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
var didBecomeFirstResponder = false
init(text: Binding<String>) {
_text = text
}
func textFieldDidChangeSelection(_ textField: UITextField) {
DispatchQueue.main.async {
self.text = textField.text ?? ""
}
}
}
@Binding var text: String
var isFirstResponder: Bool = false
func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
textField.setContentHuggingPriority(.defaultHigh, for: .vertical)
textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
DispatchQueue.main.async {
textField.becomeFirstResponder()
}
return textField
}
func makeCoordinator() -> CustomTextField.Coordinator {
return Coordinator(text: $text)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
uiView.text = text
}
}
struct TestConstraintsError: View {
@State private var text = ""
var body: some View {
VStack {
Text("Input: " + text)
CustomTextField(text: $text, isFirstResponder: true)
.padding()
.border(Color.red)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With