##【環境】
Swift5
Xcode:11.3.1
##【現象】
あるViewの上に別のViewを被せて、ボタンをタップしたら被せたViewの位置をanimateで動かしています。
しかしなぜか、UITextFieldに値を入力すると、被せたViewの移動した位置がリセット(元の位置になる)されてしまいます。
##調査したこと
animateのロジックは以下です。
UIView.animate(withDuration: 0.5, delay: 0.0, animations: { self.(被せたView).frame.origin.y += 100.0 }, completion: nil)
他のUIButtonをタップしたり、UISegmentedControlをタップするだけならリセットは発生しません。
UITextFieldにフォーカスするだけでも起こらないので、UITextFieldに値が入る時に発生すると思うのですが、なぜそうなるのか、それ以上原因の追究ができませんでした。
どなたかご存知の方がいたら教えていただけると助かります。
よろしくお願いいたします。
##【追記:ViewController】
UITextFieldに関係あるところだけ抜粋します。
calc()の部分はコメントアウトしても今回の現象は発生したので関係ないと思います。
@IBOutlet weak var money: UITextField! // 入力桁数制限処理 @IBAction func moneyEdintingChanged(_ sender: UITextField) { guard let strInputMoney = sender.text else { return } sender.text = String(strInputMoney.prefix(maxAmountLength)) } // フォーカスイン処理 @IBAction func moneyEditingDidBegin(_ sender: UITextField) { let strInputMoney :String = sender.text ?? "" sender.text = self.exceptComma(strMoney: strInputMoney) } // フォーカスアウト処理 @IBAction func moneyEditingDidEnd(_ sender: UITextField) { let intInputMoney: Int = Int(sender.text!) ?? 0 guard intInputMoney != 0 else { return } sender.text = self.addComma(intMoney: intInputMoney) // 計算処理 self.calc() } // 3桁区切りのカンマがあれば除外する func exceptComma(strMoney: String) -> String { return strMoney.replacingOccurrences(of: ",", with: "") } // 3桁区切りのカンマを付ける func addComma(intMoney: Int) -> String { let formatter = NumberFormatter() formatter.numberStyle = NumberFormatter.Style.decimal formatter.groupingSeparator = "," formatter.groupingSize = 3 return formatter.string(from: NSNumber.init(integerLiteral: intMoney))! } func calc() { // 色々計算する } // キーボードを非表示にする override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { self.view.endEditing(true) }
Xcode11.2.1 + シミュレータiOS13.2.2 ではViewがリセットする事象は発生しませんでした。
もし可能であれば、対象のViewControllerのソースを追記頂くことは可能でしょうか?もしくは、UITextFieldのDelegateを実装しているなら、関連するDelegate処理を追記頂きたいです。
tsuki01様
ご回答ありがとうございました。
発生しないのですね。。
ViewControllerをUITextFieldに関係ある部分だけ抜粋して載せました。
なお、Delegateは実装しておりません。
delegateを実装せずに、textFieldを動というのは信じられませんが、
例として、
- UIButtonのタップ
- UISegmentedControlのタップ
- UITextFieldにフォーカスをあてる
- キーボードが表示される
という、4つの動作では、viewControllerの`viewDidLayoutSubviews()`は呼ばれません。
UITextFieldに文字が入力されると`viewDidLayoutSubviews()`が呼ばれてレイアウトの変更が行われます。
例えば、UIButtonを押した際に、↓のようにボタンのタイトルを変更すると、viewDidLayoutSubviews()が呼ばれるので
@IBAction func btnDidTap(_ sender: UIButton) {
sender.titleLabel?.text = "B"
}
同じ現象が起こると思います。
追加のアドバイスありがとうございます。勉強になります。
以下の条件が揃えば、私の環境でも同じ様な事象が発生しました。
質問者様と同じ条件になっているかは不明ですが、念の為共有しておきます。
・UITextField編集時にFrameの値がリセットされてしまう場合の条件例
1、AutoLayout設定済み
2、"viewDidLayoutSubviews()"実装済み
3、"viewDidLayoutSubviews()"メソッド内で、「被せたView」のFrameを設定している
返答が遅くなりました。
回答いただきありがとうございます。
>delegateを実装せずに、textFieldを動というのは信じられませんが、
storyboardを使っています。
delegateを明示的に書いてはいませんが、アクションは設定しています。
誤解を招く書き方ですみません。
AutoLayoutは設定しています。
viewDidLayoutSubviews()も呼んでいましたが、そこで特にFrameをリセットするような処理は入れていません。
試しにviewDidLayoutSubviews()はコメントアウトしてみましたが、特に挙動に変化はありませんでした。
それじゃ、あれですね、layoutの設定と変更の方法が混在していて適当で
layoutSubviews()が呼ばれる際に問題がおこってるやつですね。
どっちかで統一されたほうがよいかと。
なるほど・・・AutoLayoutの設定が生き返る(という表現が正しいか分からないですが)ため、元の場所にリセットされてしまうということですね。
NSLayoutConstraintを使って、AutoLayoutの値自体を更新しなければいけないということが分かりました。
ありがとうございました。
回答2件
あなたの回答
tips
プレビュー

