首页 > 解决方案 > 在继承的类中覆盖 NSLayoutConstraint

问题描述

我的代码中有两个类,一个是NameCell,它包含一个带有文本的简单 UILabel。第二个是NameValueCell,它继承自该类,但也添加了属性UIView *valueView

需要更改一个布局约束。我正在寻找一种方法来覆盖:

H:|[nameView]|-nameView应该占据全宽NameCell

H:|[nameView][valueView(==nameView)]|-宽度nameViewvalueView应为 1:1 英寸NameValueCell

覆盖 NSLayoutConstraint 的最佳实践是什么?我必须坚持在我的代码中继承,因为我的应用程序需要许多不同的 UITableViewCell 特化。

NameCell.h:

@interface NameCell : UITableViewCell

@property (nonatomic, retain) IBOutlet UIView *nameView;
@property (nonatomic, retain) IBOutlet UILabel *nameLabel;

@end

NameValueCell.h:

@interface NameValueCell : NameCell

@property (nonatomic, retain) IBOutlet UIView *valueView;

@end

NameCell.m:

@implementation NameCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

        UIView *nameView = [[UIView alloc] init];
        self.nameView = nameView;
        [self.contentView addSubview:self.nameView];

        UILabel *nameLabel = [[UILabel alloc] init];
        self.nameLabel = nameLabel;
        [self.nameView addSubview:self.nameLabel];

        NSDictionary *views = NSDictionaryOfVariableBindings(nameView, nameLabel);
        NSArray *constraints;

        // The constraint that should be overridden
        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameView]|"
                                                              options: 0
                                                              metrics:nil
                                                                views:views];

        [self.contentView addConstraints:constraints];        
    }
    return self;
}

@end

NameValueCell.m:

@implementation NameValueCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        NSString *reuseID = reuseIdentifier;

        UIView *valueView = [[UIView alloc] init];
        self.valueView = valueView;
        [self.contentView addSubview:self.valueView];

        NSDictionary *views = @{
                                @"nameView": self.nameView,
                                @"nameLabel": self.nameLabel,
                                @"valueView": self.valueView
                                };
        NSArray *constraints;

        // The overriding constraint
        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameView][valueView(==nameView)]|"
                                                                       options: 0
                                                                       metrics:nil
                                                                         views:views];

        [self.contentView addConstraints:constraints];        
    }
    return self;
}

@end

标签: iosobjective-cautolayoutnslayoutconstraintios-autolayout

解决方案


第一:不添加约束;激活它们。它更简单,更不容易出错。

好吧。只需在 NSArray 实例变量中保留对可能需要替换的约束的引用:

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameView]|"
                                                      options: 0
                                                      metrics:nil
                                                        views:views];
self.removeableConstraints = constraints; // an instance property
[NSLayoutConstraint activateConstraints: constraints];

现在所有子类所要做的就是停用 self.removeableConstraints和激活它的替代约束。

[NSLayoutConstraint deactivateConstraints: self.removeableConstraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameView][valueView(==nameView)]|"
                                                      options: 0
                                                      metrics:nil
                                                        views:views];
[NSLayoutConstraint activateConstraints: constraints];

这是交换约束的一般模式,这里的类/子类关系没有理由不使用它。


推荐阅读