Ios 使用序列图像板中的标识符集获取对NSLayoutConstraint的引用
我正在使用故事板设置按钮的约束。我在约束的属性中看到了一个选项“Identifier” 我想引用这个约束,在代码中更改它的值,移动一个对象 如何从该标识符获取对此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
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
}