質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

1351閲覧

animateさせて動かしたViewの位置がリセットされてしまう

is_jun

総合スコア5

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2020/04/26 23:47

編集2020/04/27 04:12

##【環境】
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) }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tsuki01

2020/04/27 02:10

Xcode11.2.1 + シミュレータiOS13.2.2 ではViewがリセットする事象は発生しませんでした。 もし可能であれば、対象のViewControllerのソースを追記頂くことは可能でしょうか?もしくは、UITextFieldのDelegateを実装しているなら、関連するDelegate処理を追記頂きたいです。
is_jun

2020/04/27 04:14

tsuki01様 ご回答ありがとうございました。 発生しないのですね。。 ViewControllerをUITextFieldに関係ある部分だけ抜粋して載せました。 なお、Delegateは実装しておりません。
退会済みユーザー

退会済みユーザー

2020/04/27 12:59 編集

delegateを実装せずに、textFieldを動というのは信じられませんが、 例として、 - UIButtonのタップ - UISegmentedControlのタップ - UITextFieldにフォーカスをあてる - キーボードが表示される という、4つの動作では、viewControllerの`viewDidLayoutSubviews()`は呼ばれません。 UITextFieldに文字が入力されると`viewDidLayoutSubviews()`が呼ばれてレイアウトの変更が行われます。 例えば、UIButtonを押した際に、↓のようにボタンのタイトルを変更すると、viewDidLayoutSubviews()が呼ばれるので @IBAction func btnDidTap(_ sender: UIButton) { sender.titleLabel?.text = "B" } 同じ現象が起こると思います。
tsuki01

2020/04/27 15:40

追加のアドバイスありがとうございます。勉強になります。 以下の条件が揃えば、私の環境でも同じ様な事象が発生しました。 質問者様と同じ条件になっているかは不明ですが、念の為共有しておきます。 ・UITextField編集時にFrameの値がリセットされてしまう場合の条件例 1、AutoLayout設定済み 2、"viewDidLayoutSubviews()"実装済み 3、"viewDidLayoutSubviews()"メソッド内で、「被せたView」のFrameを設定している
is_jun

2020/04/30 00:54

返答が遅くなりました。 回答いただきありがとうございます。 >delegateを実装せずに、textFieldを動というのは信じられませんが、 storyboardを使っています。 delegateを明示的に書いてはいませんが、アクションは設定しています。 誤解を招く書き方ですみません。 AutoLayoutは設定しています。 viewDidLayoutSubviews()も呼んでいましたが、そこで特にFrameをリセットするような処理は入れていません。 試しにviewDidLayoutSubviews()はコメントアウトしてみましたが、特に挙動に変化はありませんでした。
退会済みユーザー

退会済みユーザー

2020/04/30 03:48 編集

それじゃ、あれですね、layoutの設定と変更の方法が混在していて適当で layoutSubviews()が呼ばれる際に問題がおこってるやつですね。 どっちかで統一されたほうがよいかと。
is_jun

2020/04/30 06:10

なるほど・・・AutoLayoutの設定が生き返る(という表現が正しいか分からないですが)ため、元の場所にリセットされてしまうということですね。 NSLayoutConstraintを使って、AutoLayoutの値自体を更新しなければいけないということが分かりました。 ありがとうございました。
guest

回答2

0

ベストアンサー

viewDidLayoutSubviews() 内でレイアウトの設定を行っていれば気づくはずなのでそんなことはないと思いますが、それ以外が思い浮かばないので念の為。


ライフサイクル的な問題で、viewDidLayoutSubviews()内でレイアウトを設定しなければならない場合は、初回設定時のみ実行されるように工夫してください。例えば↓

swift

1override func viewDidLayoutSubviews() { 2 super.viewDidLayoutSubviews() 3 4 setLayout?() 5} 6 7lazy var setLayout: (()->())? = { 8 self.hogeView.frame = self.fugaView.frame 9 return nil 10}() 11

追記
コードの掲示がないのでわかりませんが、
たぶんこんなかんじになってるんだと思う

イメージ説明

投稿2020/04/27 17:05

編集2020/04/30 03:46
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

is_jun

2020/04/30 06:11

はい!まさしく上記のような動きでした。 いただいたgitを参考にさせていただき、NSLayoutConstraintを更新することで位置がリセットされないことを確認できました。 ありがとうございました。
guest

0

質問への追記依頼をお願いした者です。追記頂きありがとうございました。
やはりこちら側でパッと試した感じだと発生せずです。。

他に原因が考えられるのは、アニメーション箇所以外でViewのFrameを変更していないか?でしょうか。
また、↓のリンクに、AutoLayoutが原因でFrameがリセットされる様なことが書いてました。古い記事ですが、もしAutoLayoutを利用していたら参照お願いいたします。
UIView frames reset when using autolayout

※こちら側の環境
・Xcode11.2.1
・シミュレータiOS13.2.2
・Swift5

※補足
質問者様と全く同じレイアウトは作れませんので、赤いViewが親Viewで、青いViewが被せるViewをイメージして配置しました。

イメージ説明

Swift

1// こちら側のViewController処理内容 2import UIKit 3 4class ViewController: UIViewController { 5 6 @IBOutlet weak var money: UITextField! 7 @IBOutlet weak var addView: UIView! 8 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 } 13 14 15 @IBAction func btnClick(_ sender: Any) { 16 UIView.animate(withDuration: 0.5, delay: 0.0, animations: { 17 self.addView.frame.origin.y += 100.0 18 }, completion: nil) 19 } 20 21 // 入力桁数制限処理 22 @IBAction func moneyEdintingChanged(_ sender: UITextField) { 23 guard let strInputMoney = sender.text else { return } 24 sender.text = String(strInputMoney.prefix(10)) 25 } 26 27 // フォーカスイン処理 28 @IBAction func moneyEditingDidBegin(_ sender: UITextField) { 29 let strInputMoney :String = sender.text ?? "" 30 sender.text = self.exceptComma(strMoney: strInputMoney) 31 } 32 33 // フォーカスアウト処理 34 @IBAction func moneyEditingDidEnd(_ sender: UITextField) { 35 let intInputMoney: Int = Int(sender.text!) ?? 0 36 guard intInputMoney != 0 else { return } 37 sender.text = self.addComma(intMoney: intInputMoney) 38 // 計算処理 39 self.calc() 40 } 41 42 // 3桁区切りのカンマがあれば除外する 43 func exceptComma(strMoney: String) -> String { 44 return strMoney.replacingOccurrences(of: ",", with: "") 45 } 46 47 // 3桁区切りのカンマを付ける 48 func addComma(intMoney: Int) -> String { 49 let formatter = NumberFormatter() 50 formatter.numberStyle = NumberFormatter.Style.decimal 51 formatter.groupingSeparator = "," 52 formatter.groupingSize = 3 53 return formatter.string(from: NSNumber.init(integerLiteral: intMoney))! 54 } 55 56 func calc() { 57 // 色々計算する 58 } 59 60 // キーボードを非表示にする 61 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 62 self.view.endEditing(true) 63 } 64}

投稿2020/04/27 05:41

tsuki01

総合スコア1751

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

is_jun

2020/04/27 05:51

tsuki01様 ご検証いただきありがとうございました! 感謝いたします。 自分でも色々関係ありそうなところ、なさそうなところをコメントアウトしてデバッグしてみても、今のところ手がかりが掴めないところです。 それでも他の方の環境では発生しないことが分かっただけでも大変ありがたいです。 いただいたリンク先を拝見し、もう少し調査してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問