アプリがバックグラウンドで実行されているときに制約がリセットされる-iOS 13


8

通常、ビューの先頭と末尾の制約を設定しました。私はその高さを静的な325に設定しました。また、下部の制約については、2つの制約1.メインビューの下部の制約をビューの下部の制約に設定しました。2.メインビューの下部の制約とビューの上部の制約。ユーザーのアクションでは、アニメーションでビューを非表示にするだけです。したがって、ビューが画面に表示され、アプリがバックグラウンドになると、ビューの制約が自動的に変更され、ビューが非表示になります。この問題はiOS 13デバイスでのみ発生します。

viewWillAppear()の制約を更新しようとしましたが、iOS 13では、アプリがバックグラウンドからアクティブ化されたときにViewControllersのviewWillAppearも呼び出されません。また、これは制約を更新するための良いアイデアだとは思いません。

ストーリーボード

クラスファイル

class ViewController: UIViewController {

    @IBOutlet weak var topConstraint: NSLayoutConstraint!
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
            self.topConstraint.isActive = false
            self.bottomConstraint.isActive = true
            UIView.animate(withDuration: 0.3) {
                self.view.layoutIfNeeded()
            }
        }
    }
}

アプリの状態がフォアグラウンドからバックグラウンドに、またはその逆に変化したときに、制約を変更または更新したくありません。

同じことで私を助けてください。

TIA


1
制約と明示的なフレーム設定を混在させているため、通常は問題が発生します。あなたが何を望んでいるかがはっきりしていません...ビューが読み込まれたらcontentView、下部に配置したいので(「オフスクリーン」になっています)、アニメーションを表示して上に移動します...その後、アプリはバックグラウンドに移動します、そしてアプリがフォアグラウンドに戻ったときにビューを表示したままにしますか?新しいアニメーションはありませんか?
DonMag

はい。これだけ好きです。実際、私がviewWillAppear()で記述したコードは、ユーザーのアクションで実行されます。しかし、説明のために、1つのデモを作成しました。
Rajat Mishra

アニメーションの位置/サイズが制約のみで明示的に機能している(明示的な.frame = ...ステートメントがない)と仮定すると、コードは正常に機能しているはずです。イベントで他のコードが実行されていない限り、アプリがバックグラウンドからフォアグラウンドに移行するときに呼び出されるViewDidLoad()べきではありません
DonMag

回答:


6

この問題も満たしました。制約InstalledがInterface Builderでチェックされていない場合、制約がリセットされ続けることに注意してください。したがって、回避策として、すべての制約InstalledをIBに保持しisActive、コードだけで状態を変更します。

ここに画像の説明を入力してください


これは実際には機能しませんでした。falseに設定isActiveすると、アプリがバックグラウンドに戻ったときにアクティブに戻ります。
クリスバセリ

2

優先順位を設定して値を反転させることで、ソリューションを実現できます。

 if !isShowing{
       self.bottomConstraint.priority = UILayoutPriority(rawValue: 250)
       self.topConstraint.priority = UILayoutPriority(rawValue: 750)
   }else{
       self.bottomConstraint.priority = UILayoutPriority(rawValue: 750)
       self.topConstraint.priority = UILayoutPriority(rawValue: 200)
   }
   isShowing = !isShowing
   self.subview.layoutIfNeeded()

2

この問題はiOS 13.0以降でのみ発生していることがわかりました。ViewDidLayoutSubviewsで制約を変更してみてください

      override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
            self.bottomConstraint.isActive = false
            self.topConstraint.isActive = true
    self.view.layoutIfNeeded()
}

それは魅力のように働きました。しかし、なぜそれがiOS 13.0だけで起こっているのですか?&なぜviewWillAppearが呼び出されないのですか?
スハイル

1

私にとってうまくいった回避策は、をリッスンしUIApplication.willEnterForegroundNotificationisActiveこの時点ですべての制約を設定することでした。

この通知は公開されているようだ後に、システムが(間違って)自分のIB状態にすべての制約をリセットし、前のアプリが再び見えるようになります。ですから、制約を修正する絶好の機会です。


0

「アプリがバックグラウンドからフォアグラウンドになったときに通知する方法」を知る必要がある場合。すべてにシグナルを送信するには、NotificationCenterを使用する必要があります。しかし、これは良い習慣ではありません。

多分あなたはあなたの目的を言うことができます、そして私たちはあなたに異なるアプローチを与えることができます。


0

さて、私は解決策を得ました。実際には、それが解決策であるとは言えません。iOS 13.1以降のバージョンのデバイスで同じコードを実行しただけで、問題は解決しました。今のところ、この問題はiOS 13.0でのみ発生すると言えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.