web-dev-qa-db-ja.com

ストーリーボードに設定された識別子を使用してNSLayoutConstraintへの参照を取得します。

ストーリーボードを使用してボタンの制約を設定していました。制約のプロパティに「識別子」オプションが表示されました。

Screenshot of constraint's properties

この制約を参照して、コードでその値を変更し、オブジェクトを移動したいと思います。

この識別子からこのNSLayoutContraintへの参照を取得するにはどうすればよいですか。

私はドキュメントを読みました、それはこのように書かれました

@interface NSLayoutConstraint (NSIdentifier)
/* For ease in debugging, name a constraint by setting its identifier, which will be printed in the constraint's description.
 Identifiers starting with UI and NS are reserved by the system.
 */
@property (nullable, copy) NSString *identifier NS_AVAILABLE_IOS(7_0);

@end

だから私はそれがデバッグ目的のためであることを理解しました。

入手して使用したい場合はどうなりますか?私はこのリンクを見ましたが、満足のいく答えは得られませんでした: ポインタによってNSLayoutConstraintの識別子を取得する方法?

18
Sam Shaikh

前の回答で提供されたロジックを拡張に外挿したい場合があります。

_extension UIView {
    /// Returns the first constraint with the given identifier, if available.
    ///
    /// - Parameter identifier: The constraint identifier.
    func constraintWithIdentifier(_ identifier: String) -> NSLayoutConstraint? {
        return self.constraints.first { $0.identifier == identifier }
    }
}
_

その後、次を使用して任意の場所で制約にアクセスできます。

myView.constraintWithIdentifier("myConstraintIdentifier")

編集:キックのためだけに、上記のコードを使用して、すべての子UIViewでその識別子を持つすべての制約を見つける拡張機能を次に示します。最初に見つかった制約の代わりに配列を返すように関数を変更する必要がありました。

_    func constraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
        return self.constraints.filter { $0.identifier == identifier }
    }

    func recursiveConstraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
        var constraintsArray: [NSLayoutConstraint] = []

        var subviews: [UIView] = [self]

        while !subviews.isEmpty {
            constraintsArray += subviews.flatMap { $0.constraintsWithIdentifier(identifier) }
            subviews = subviews.flatMap { $0.subviews }
        }

        return constraintsArray
    }
_
10
Isaiah Turner

Swiftでは、

 let filteredConstraints = button.constraints.filter { $0.identifier == "identifier" }
 if let yourConstraint = filteredConstraints.first {
      // DO YOUR LOGIC HERE
 }
23
Venk

Swift

これをうまく処理する簡単なNSView拡張を作成しました。

extension NSView {
    func constraint(withIdentifier: String) -> NSLayoutConstraint? {
        return self.constraints.filter { $0.identifier == withIdentifier }.first
    }
}

使用法:

if let c = button.constraint(withIdentifier: "my-button-width") {
    // do stuff with c
}
12
quemeful

ボタンのアウトレットが設定されているので、参照できるようになっていると思います。したがって、最初に、ボタンからビューの制約を取得します。次に、配列をループし、各反復で、各制約のidentiferプロパティをInterface Builderで入力した値と比較します。 Objective-Cでコーディングしているようですので、Objective-Cのコードサンプルを以下に示します。 @ "identifier"をInterface Builderで設定した値に変更します。

NSArray *constraints = [button constraints];
int count = [constraints count];
int index = 0;
BOOL found = NO;

while (!found && index < count) {
    NSLayoutConstraint *constraint = constraints[index];
    if ( [constraint.identifier isEqualToString:@"identifier"] ) {
        //save the reference to constraint
        found = YES;
    }

    index++;
}
8
strwils

検索を簡略化し、スーパービューの祖先リストを上に追加しました。

+ (NSLayoutConstraint *) findConstraintNamed:(NSString *)identifierTarget startWith:(UIView *)aView;    
{    
    // walk upward from item through ancestors  
    UIView *currentView = aView;            

    while (currentView != nil)    
    {    
        NSArray *constraints = [currentView constraints];    
        NSInteger foundConstraintIndex = [constraints indexOfObjectPassingTest:^BOOL(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {   
            return [((NSLayoutConstraint *)obj).identifier isEqualToString:identifierTarget];    
        }];


        if (foundConstraintIndex != NSNotFound)    
        {    
            return constraints[foundConstraintIndex];    
        }                

        // not found, so walk up the ancestor chain    
        currentView = currentView.superview;    
    }    

    return nil;  // not found anywhere in item or ancestors!  :(    
}
1

これは、共通のビューコンテナ内のボタンセットのサイズを変更する場合に機能します。各サブビュー/ボタンは、共通の識別子(「高さ」など)を使用する必要があります。

@IBAction func btnPressed(_ sender: UIButton) {
    for button in self.btnView.subviews{
        for constraint in button.constraints{
            if constraint.identifier == "height"{
                constraint.constant = constraint.constant == 0 ? 30:0
            }
        }
    }
    UIView.animate(withDuration: 0.3) { () -> Void in
        self.view.layoutIfNeeded()
    }
}
0
Yarm