3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TextFieldの矛盾する制約

Last updated at Posted at 2024-09-22

以下の実装を実行すると,ユーザーがフォーカスするテキストフィールドを切り替え,キーボードタイプも変更された時,制約が矛盾しているため一部の制約を無視したとコンソール上で警告される.
(iOS 18.0, Xcode 16.0.0 RC)

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            TextField("abc", text: .constant(""))
                .keyboardType(.default)
            TextField("123", text: .constant(""))
                .keyboardType(.numberPad)
        }
    }
}
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:0x600002178550 'accessoryView.bottom' _UIRemoteKeyboardPlaceholderView:0x10600df80.bottom == _UIKBCompatInputView:0x10472cdb0.top   (active)>",
    "<NSLayoutConstraint:0x60000216c690 'assistantHeight' SystemInputAssistantView.height == 45   (active, names: SystemInputAssistantView:0x106011380 )>",
    "<NSLayoutConstraint:0x6000021623f0 'assistantView.bottom' SystemInputAssistantView.bottom == _UIKBCompatInputView:0x10472cdb0.top   (active, names: SystemInputAssistantView:0x106011380 )>",
    "<NSLayoutConstraint:0x60000217a030 'assistantView.top' V:[_UIRemoteKeyboardPlaceholderView:0x10600df80]-(0)-[SystemInputAssistantView]   (active, names: SystemInputAssistantView:0x106011380 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000216c690 'assistantHeight' SystemInputAssistantView.height == 45   (active, names: SystemInputAssistantView:0x106011380 )>

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.

これだけでは何を言っているか分かりづらいので,以下のサイトにコピペする

と,視覚化して教えてくれる.

image.png

以下のようにUITextFieldをそのまま使うと,同様の問題は発生しなかった.

struct UIViewRepresenter: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let view = UIView()
        let textFieldA = prepareTextField()
        textFieldA.text = "abc"
        view.addSubview(textFieldA)

        let textFieldB = prepareTextField()
        textFieldB.text = "123"
        textFieldB.keyboardType = .numberPad
        view.addSubview(textFieldB)

        NSLayoutConstraint.activate([
            textFieldA.widthAnchor.constraint(equalTo: view.widthAnchor),
            textFieldA.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            textFieldB.widthAnchor.constraint(equalTo: view.widthAnchor),
            textFieldB.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.05),
            textFieldB.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
        return view
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {
    }

    func prepareTextField() -> UITextField {
        let textField = UITextField()
        textField.backgroundColor = .gray
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }
}

多分SwiftUI.TextFieldの実装がイケていないのかな?
(SwiftUIはClosed Sourceだから,その範疇で起こる不具合は全部Appleが悪いと思っている)

なお,以下によると,iOS 13ではUIKitのみでも同様の警告が出ていたらしい.

警告を放っておくのは落ち着かないが,挙動に問題はなさそうなので,このままにしておく.

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?