使用故事板中设置的标识符获取对 NSLayoutConstraint 的引用
Get reference to NSLayoutConstraint using Identifier set in storyboard
我正在使用故事板设置按钮的约束。我在约束的属性中看到了一个选项 "Identifier"。
我想引用这个约束,在代码中改变它的值,移动一个对象。
我如何从这个标识符中获得对这个 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
所以我意识到这是为了调试目的。
如果我想得到它并使用它怎么办?我看到了这个link,但是没有给出满意的答案:How to get NSLayoutConstraint's identifier by Its pointer?
我假设您已经为按钮设置了插座,因此您可以参考它。所以首先,从您的按钮中检索视图的约束。然后遍历数组并在每次迭代中将每个约束的标识符 属性 与您在 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++;
}
在Swift3,
let filteredConstraints = button.constraints.filter { [=10=].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 { [=10=].identifier == withIdentifier }.first
}
}
用法:
if let c = button.constraint(withIdentifier: "my-button-width") {
// do stuff with c
}
对于在公共视图容器中调整一组按钮的大小,这是可行的。每个 subview/button 必须使用共同的标识符(例如 "height")。
@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()
}
}
我简化了搜索并在父视图的祖先列表中添加:
+ (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 { [=10=].identifier == identifier }
}
}
然后您可以使用以下方法在任何地方访问任何约束:
myView.constraintWithIdentifier("myConstraintIdentifier")
编辑:
只是为了好玩,使用上面的代码,这里有一个扩展,可以在所有子 UIView 中找到具有该标识符的所有约束。必须将函数更改为 return 数组而不是找到的第一个约束。
func constraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
return self.constraints.filter { [=11=].identifier == identifier }
}
func recursiveConstraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
var constraintsArray: [NSLayoutConstraint] = []
var subviews: [UIView] = [self]
while !subviews.isEmpty {
constraintsArray += subviews.flatMap { [=11=].constraintsWithIdentifier(identifier) }
subviews = subviews.flatMap { [=11=].subviews }
}
return constraintsArray
}
我正在使用故事板设置按钮的约束。我在约束的属性中看到了一个选项 "Identifier"。
我想引用这个约束,在代码中改变它的值,移动一个对象。
我如何从这个标识符中获得对这个 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
所以我意识到这是为了调试目的。
如果我想得到它并使用它怎么办?我看到了这个link,但是没有给出满意的答案:How to get NSLayoutConstraint's identifier by Its pointer?
我假设您已经为按钮设置了插座,因此您可以参考它。所以首先,从您的按钮中检索视图的约束。然后遍历数组并在每次迭代中将每个约束的标识符 属性 与您在 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++;
}
在Swift3,
let filteredConstraints = button.constraints.filter { [=10=].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 { [=10=].identifier == withIdentifier }.first
}
}
用法:
if let c = button.constraint(withIdentifier: "my-button-width") {
// do stuff with c
}
对于在公共视图容器中调整一组按钮的大小,这是可行的。每个 subview/button 必须使用共同的标识符(例如 "height")。
@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()
}
}
我简化了搜索并在父视图的祖先列表中添加:
+ (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 { [=10=].identifier == identifier }
}
}
然后您可以使用以下方法在任何地方访问任何约束:
myView.constraintWithIdentifier("myConstraintIdentifier")
编辑: 只是为了好玩,使用上面的代码,这里有一个扩展,可以在所有子 UIView 中找到具有该标识符的所有约束。必须将函数更改为 return 数组而不是找到的第一个约束。
func constraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
return self.constraints.filter { [=11=].identifier == identifier }
}
func recursiveConstraintsWithIdentifier(_ identifier: String) -> [NSLayoutConstraint] {
var constraintsArray: [NSLayoutConstraint] = []
var subviews: [UIView] = [self]
while !subviews.isEmpty {
constraintsArray += subviews.flatMap { [=11=].constraintsWithIdentifier(identifier) }
subviews = subviews.flatMap { [=11=].subviews }
}
return constraintsArray
}