Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用序列图像板中的标识符集获取对NSLayoutConstraint的引用_Ios_Objective C_Cocoa Touch_Uistoryboard_Nslayoutconstraint - Fatal编程技术网

Ios 使用序列图像板中的标识符集获取对NSLayoutConstraint的引用

Ios 使用序列图像板中的标识符集获取对NSLayoutConstraint的引用,ios,objective-c,cocoa-touch,uistoryboard,nslayoutconstraint,Ios,Objective C,Cocoa Touch,Uistoryboard,Nslayoutconstraint,我正在使用故事板设置按钮的约束。我在约束的属性中看到了一个选项“Identifier” 我想引用这个约束,在代码中更改它的值,移动一个对象 如何从该标识符获取对此nslayoutcontain的引用 我看过文件,是这样写的 @interface NSLayoutConstraint (NSIdentifier) /* For ease in debugging, name a constraint by setting its identifier, which will be printed

我正在使用故事板设置按钮的约束。我在约束的属性中看到了一个选项“Identifier”

我想引用这个约束,在代码中更改它的值,移动一个对象

如何从该标识符获取对此
nslayoutcontain
的引用

我看过文件,是这样写的

@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
所以我意识到这是为了调试


如果我想得到它并使用它呢?我看到了这个链接,但没有给出令人满意的答案:

我想您已经为按钮设置了一个插座,因此您可以使用它。因此,首先,从按钮中检索视图的约束。然后循环遍历数组,并在每次迭代中将每个约束的identifer属性与您在Interface Builder中输入的值进行比较。看起来您正在使用Objective-C进行编码,下面是Objective-C代码示例。将@“标识符”更改为在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++;
}
NSArray*约束=[按钮约束];
int count=[constraints count];
int指数=0;
BOOL-found=NO;
而(!发现和索引<计数){
NSLayoutConstraint*约束=约束[索引];
如果([constraint.identifier IsequalString:@“identifier”]){
//保存对约束的引用
发现=是;
}
索引++;
}

Swift 3

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

Swift 3

我编写了一个快速的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
}

对于调整公共视图容器中的一组按钮的大小,此操作有效。每个子视图/按钮必须使用公共标识符(例如“高度”)


我简化了搜索,并在超级视图的祖先列表中添加了:

+ (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!  :(    
}

您可能希望将前面答案中提供的逻辑推断为扩展

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.constraintWithiIdentifier(“myConstraintID标识符”)

编辑: 对于kicks,使用上面的代码,这里有一个扩展,可以在所有子视图中查找具有该标识符的所有约束。必须更改函数以返回数组,而不是找到的第一个约束

    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
    }

最好在这里解释一下,将约束链接到类中的IBOutlet属性要简单得多。从“new Reference outlet”拖动,就像从任何其他元素(如标签或文本字段)拖动一样。感谢您的建议,但我使用的是这个东西,所以希望编写更小的代码,所以我正在搜索更好的方法@PAULW11插座是零代码解决方案,是苹果公司推荐的方法。搜索约束数组成本更高,代码更多,也更脆弱。@Paulw11如果需要为插座设置新约束,该怎么办?出口将为零。您不能这样做,但例如,您需要更改约束的乘数,并且仅在初始化阶段设置此参数。约束不会存储在按钮本身上。约束必须安装在约束所涉及的所有视图的公共祖先视图上。它可能安装在最近的共同祖先(可能是其中一个涉及的视图本身)上,但理论上可能安装在更遥远的祖先上。对于问题中显示的约束,它将位于按钮的superview上。这就是为什么按标识符搜索是如此糟糕的方法的部分原因。@Ken Thomases是的,同意这是一个糟糕的选择。然而,iOS开发人员坚持认为,无论出于何种原因,他/她都希望从代码中检索它。按钮本身用于说明逻辑,但是的,约束可能由视图本身(宽度或高度)或父视图持有,具体取决于约束的类型。@Kenthomass,感谢您的回答和评论,但我认为迭代整个约束和从数组中精选一个约束很差。这就像我做了一组约束,然后从组中找到它们。苹果必须允许用户从其标识符中找到约束。@iOSDeveloper,这不是我的答案;是strwils'。我不明白你说的“团体”是什么意思。但关于“苹果必须允许用户从其标识符中找到约束”,你会发现事实并非如此。除了这种手动搜索方法之外,没有任何机制可以通过其标识符来查找约束,因为您不应该这样做。按照Paulw11在评论中的建议:使用一个outlet。你不应该在类中创建一个
@IBOutlet
作为
NSLayoutConstraint
,并链接它吗?
    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
    }