動的な高さを持つビューがあり、実行時にこのビューの高さの優先順位を変更しようとしています。
これが私のコードの一部です。
if (index == 0) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.priority = 1000;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.priority = 500;
}
ボタンアクションでインデックスを変更しています。このコードを実行すると、次のエラーが表示されます。
*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174
ここで私の間違いは何ですか?
NSLayoutConstraint
クラスリファレンス に記載されているとおり:
優先順位は、非必須から必須に、または必須から非必須に変更されることはありません。 OS Xの
NSLayoutPriorityRequired
またはiOSのUILayoutPriorityRequired
の優先度が低い優先度に変更された場合、または制約が追加された後に低い優先度が必要な優先度に変更された場合、例外がスローされます見る。あるオプションの優先度から別のオプションの優先度への変更は、制約がビューにインストールされた後でも許可されます。
1000ではなく999の優先度を使用します。技術的に言えば絶対に必要というわけではありませんが、他の何よりも優先度が高くなります。
Cyrilleの答えに少し追加したいと思います。
コードで制約を作成する場合は、アクティブにする前に優先度を設定してください。例えば:
surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;
これにより、実行時例外が発生します。
優先度を必須からインストール済みの制約に変更する(またはその逆)ことはサポートされていません。
正しい順序は次のとおりです。
surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;
これを常に扱ってきた方法は、制約定数を変更せず、優先度だけを変更することです。たとえば、あなたの状況では2つの高さの制約があります。
heightConstraintOne (who's height is set in the storyboard at 150, and priority set at 750)
heightConstraintTwo (who's height is set in the storyboard at 0, and priority set at 250)
ビューを非表示にする場合は、次のことを行います。
heightConstraintTwo.priority = 999;
同様に、ビューを表示する場合:
heightConstraintTwo.priority = 250;
Swiftバージョン:
myContraint.priority = UILayoutPriority(999.0)
このシナリオが誰かに役立つことを願っています:私は2つの制約がありました、それらは互いに反対でした、つまり、同時に満たすことができなかったことを意味しますコードでそれらを変更すると、このエラーが発生しました:
キャッチされていない例外 'NSInternalInconsistencyException'によるアプリの終了、理由: 'インストール済み制約(またはその逆)での優先度の必須から無効への変更はサポートされていません。優先度250を渡し、既存の優先度は1000でした。」
次に、それらを.defaultHighおよび.defaultLowの値でviewDidLoad関数で初期化したところ、問題が修正されました。
NSLayoutConstraints class
内部UIKit Module
によると
制約の優先度レベルがUILayoutPriorityRequiredより小さい場合、オプションです。優先度の高い制約は、優先度の低い制約よりも先に満たされます。制約の満足度は、すべてまたはゼロではありません。制約「a == b」がオプションである場合、それは「abs(a-b)」を最小化しようとすることを意味します。このプロパティは、初期設定の一部として、またはオプションの場合にのみ変更できます。制約がビューに追加された後、NSLayoutPriorityRequiredの優先度が変更されると、例外がスローされます。
例:-さまざまな優先度のUIButton
制約-
func setConstraints() {
buttonMessage.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -10).isActive = true
let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 10)
leading.isActive = true
let widthConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
trailingToSuperView.priority = 999
trailingToSuperView.isActive = true
//leading.isActive = false//uncomment & check it will align to right of the View
buttonMessage.addConstraints([widthConstraint,heightConstraint])
}
これで、制約にIBOutlet接続を使用して、このコードを使用できます。
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)