Xcode Constraint Break When Switching Between Text Fields Without Dismissing Keyboard

Xcode Constraint Break When Switching Between Text Fields Without Dismissing Keyboard

The layout constraint error message has nothing to do with your layout.

It's an internal issue (could be considered a bug) with the Input Assistant View - the auto-complete options shown above the keyboard.

If you use Debug View Hierarchy you can find the culprit listed in the error message: TUISystemInputAssistantView

You can ignore this error / warning message, as it is out of your hands.

Edit

The error / warning message shows:

"<NSLayoutConstraint:0x281f15bd0 'assistantHeight' TUISystemInputAssistantView:0x14602a340.height == 55   (active)>",

Here is what you can find using Debug View Hierarchy:

Sample Image

As you can see, the "offending element" is the TUISystemInputAssistantView which is part of iOS internal functionality.

SwiftUI Software keyboard + two TextFields = Constraint conflict



have you resolve it yet?
if not maybe this would help!
GeometryReader.init { geometry in
ScrollView.init {
VStack.init(alignment: .leading, spacing: nil, content: {
Text("Hello.")
.font(.custom("Helvetica-Bold", size: 32))
Text("This just my sample application using swift UI")
.padding(.init(top: 0, leading: 0, bottom: 0, trailing: (geometry.size.width * 0.35)))
.foregroundColor(.gray)
TextField.init("Email Address", text: self.$textFieldName)
.frame(width: geometry.size.width, height: 50)
.disableAutocorrection(true)
.layoutPriority(1000)
TextField.init("Email Address", text: self.$textFieldName)
.frame(width: geometry.size.width, height: 50)
.disableAutocorrection(true)
.layoutPriority(1000)
})
}
}

if you curious what happens to you constraints its because your keyboard had autocorrection in it.

using this line,

.disableAutocorrection(<#Bool?#>)
get rid of your autocorreaction tab in the top of your keyboard.

Layout Constraint Errors with simple UIToolar for keyboard inputAccessoryView

Change

let aKeyboardToolBar = UIToolbar()

to

let aKeyboardToolBar = UIToolbar(frame:CGRect(x:0, y:0, width:100, height:100))

That way it has some size to work with as you are giving it content.

SWIFT: UIView which moves up with keyboard, moves very strangely after initial move, doesn't come back down

You are doing too many things wrong for me to list, so I have just fixed your project and made a pull request. Merge the pull request into your repo and you will see that it now works fine.

Just for the record, here are some of the main things you were doing wrong:

  • You added a bottom constraint, in code, to the blue view. But you already had a bottom constraint on the blue view. Thus you now have two of them, and any change in one of them will cause a conflict. The Xcode console was telling you very clearly that this was happening, but you ignored what it told you.

  • You were changing the constraint constant but also changing the blue view center. That probably caused no harm but it was pointless. You cannot govern a view's position by its center if you are governing it with constraints; they are opposites.

  • In your show and hide methods you examined keyboardFrameBeginUserInfoKey. That's wrong. You want to examine keyboardFrameEndUserInfoKey. The question is not where the keyboard is now but where it will be when it finishes moving.

  • The animation is wrong. There is no need for a UIView animation; you are already in an animation block. Just call layoutIfNeeded and the animation will happen together with the movement of the keyboard.

  • Your entire way of speaking of and accessing constraints is wrong. You use an incorrect expression super.view (you probably meant self.view). But even more important, you attempt to access the desired constraint by saying self.constraints[2]. That sort of thing is fragile in the extreme. The correct approach is to keep a reference to the actual constraint (an instance property). In this situation, since the constraint already exists (in the storyboard), that reference can be an outlet.

So, with all that said, here's my rewrite of your code; this is the complete code needed:

class ViewController: UIViewController {

@IBOutlet weak var sampleTextField: UITextField!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
var originalConstant: CGFloat = 0

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIWindow.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIWindow.keyboardWillHideNotification, object: nil)
self.originalConstant = bottomConstraint.constant
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sampleTextField.endEditing(true)
}
}

extension ViewController {
@objc func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.bottomConstraint.constant += keyboardSize.height + 5
self.view.layoutIfNeeded()
}
}

@objc func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.bottomConstraint.constant = self.originalConstant
self.view.layoutIfNeeded()
}
}
}

With all of that said, the code is still wrong, because you are not taking account of the very real possibility that you will get a keyboardWillShow notification when the keyboard is already showing. However, I leave that for your later investigation.

Moving keyboard when editing multiple textfields with constraints swift

You must use scrollview for your uiview controller and then you can use notification for adjusting your uiview constraint.

Your UIViewController hierarchy should be like this

ContainerView --> ScrollView --> Content View --> Now Your View.

I'm suggesting you to use pod 'TPKeyboardAvoiding' for future animations in scrollview since for every controller you don't want to put notifications to shifting your UIView.

Here is link demo for your UIView shifting https://github.com/Vasu05/ScrollViewExample

Stop UITextField from expanding horizontally

Here's the problem. The text field has a tendency to size itself horizontally to its contents. The button has a tendency to size itself horizontally to its contents. Thus you have an ambiguity: those tendencies have the same priority, so the runtime doesn't know which one to collapse as the text field's text gets too long.

The solution is to adjust those priorities. You must lower the horizontal compression and hugging priorities for the text field - one point lower should be sufficient. Now the button will have a stronger tendency to match its own size to its contents, and the text field will clip its contents.

Sample Image

Keyboard dismisses on every character typed in text input in Swift

What's going on here is your view, including the UITextField gets re-created after each keystroke because your view construction is in:

viewDidLayoutSubviews(), When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.

To fix it, move the code to ViewDidLoad, so the view is created only once:

override func viewDidLoad() {
super.viewDidLoad()

self.view.backgroundColor = .white
verseTitle.delegate = self

let titleStack = UIStackView()
titleStack.axis = .horizontal
titleStack.alignment = .center
titleStack.distribution = .equalSpacing
titleStack.spacing = 8

titleStack.addArrangedSubview(verseTitle)
titleStack.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(titleStack)

NSLayoutConstraint.activate([
titleStack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
titleStack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
])
}

UITextField autolayout with margins programmatically

Usually I use for this cocoapod that is dealing with constraints, but if you need pure apple solution documentation states:

You have three choices when it comes to programmatically creating
constraints: You can use layout anchors, you can use the
NSLayoutConstraint class, or you can use the Visual Format Language.

Approach with NSLayoutConstraints in your case would be:

NSLayoutConstraint(item: textField, attribute: .Leading, relatedBy: .Equal, toItem: parentView, attribute: .LeadingMargin, multiplier: 1.0, constant: 15.0).active = true

NSLayoutConstraint(item: textField, attribute: .Trailing, relatedBy: .Equal, toItem: parentView, attribute: .TrailingMargin, multiplier: 1.0, constant: -15.0).active = true

NSLayoutConstraint(item: textField, attribute: .Top, relatedBy: .Equal, toItem: parentView, attribute: .TopMargin, multiplier: 1.0, constant: 50.0).active = true

Remember that if you don't have any constraints in the view, they would be added automatically and you'll have to deal with them and conflicts that would be created by adding new constraints on runtime. To avoid this you could either create textField manually and add it to the view or set constraints with low priority in the Interface Builder .



Related Topics



Leave a reply



Submit