web-dev-qa-db-ja.com

非アクティブにすると、弱いIBOutlet NSLayoutConstraintがnilになるのはなぜですか?

アプリにIBOutlet NSLayoutConstraintがあります。非常に簡単:

@property (nonatomic, weak) IBOutlet NSLayoutConstraint* leftConstraint;

ある時点で、この制約を無効にします。

self.leftConstraint.active = NO;

cellForRowAtIndexPath:から呼び出されるメソッドで発生します。そして、制約は上の行の直後でnilになります。ただし、このプロパティをstrongとして宣言した場合は問題ありません。nilにはなりません。誰がそれが起こるのか説明できますか?

27

アウトレットがweakの場合、唯一のstrong参照はビューのconstraintsプロパティからのものです。制約を非アクティブにすると、その配列から制約が削除されるため、これ以上強い参照はなくなります。

64
Avi

可能な回避策は、制約を非アクティブにするのではなく、優先順位を変更することです。

@property (nonatomic, weak) IBOutlet NSLayoutConstraint* leftConstraint;
(...)
self.leftConstraint.priority = 250;

その後、self.leftConstraintは破棄されません。

編集:

Xcodeは、必要な(= 1000)制約の優先順位の変更をサポートしていないため、必ず1 ... 999の範囲で切り替えてください。

7
Fran Pugl

最初に、IBOutlet変数をオプションに変更します。すなわち:

から:

@IBOutlet weak var myConstraint : NSLayoutConstraint!

に:

@IBOutlet weak var myConstraint : NSLayoutConstraint?

今後、ストーリーボードからの管理/変更を簡単にするために、新しい変数(たとえばmyConstraint_DefualtValue)を追加し、これをmyConstraint inの値に設定します- viewDidLoad

var myConstraint_DefualtValue = CGFloat(0)
override func viewDidLoad() {
    super.viewDidLoad()

    self.myConstraint_DefualtValue = self.myConstraint.constant

}

なぜ他の場所ではなくviewDidLoadに設定する必要があるかは明らかだと思います

その後、それを無効にする場合:

self.myConstraint?.isActive = false

そして、それを再アクティブ化する場合(ビューをアウトレット(myViewThatHasTheConstraint)とし、制約がheight制約であると仮定します):

self.myConstraint = self.myViewThatHasTheConstraint.heightAnchor.constraint(equalToConstant: self.myConstraint_DefualtValue);
self.myConstraint?.isActive = true
3
Mjd Mz