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

一种布局约束需要更改。我正在寻找一种替代方法:
H:|[nameView]|-nameView应该在NameCell中占据全角


H:|[nameView][valueView(==nameView)]|-nameViewvalueViewNameValueCell的宽度比应为1:1

覆盖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

最佳答案

子类希望通过添加其他子视图来增强 super class 的行为。但是在创建约束时,它也想覆盖 super class 。为此,最好的方法是排除视图创建和约束创建代码,然后在子类中,通过有选择地调用super来控制我们是扩充还是覆盖。

首先,请考虑...

// in NameCell.m initWithStyle
// super initWithStyle..., if (self) { ...
[self addCustomSubviews];
[self addCustomConstraints];

NameCell中,这些新方法应完全按照您在问题中的内联方式实现,但在子类中:(1)根本不实现init,允许 super class init调用分解后的代码,以及(2)覆盖分解后的代码如下...
// NameValueCell.m
- (void)addCustomSubviews {
    // augmenting super here, so call super...
    [super addCustomSubviews];

    // add the value view
    UIView *valueView = [[UIView alloc] init];
    // and so on
}

- (void)addCustomConstraints {
    // overriding super here, so don't call super, just add constraints
    NSDictionary *views = @{
       // and so in
}

在一个不太繁琐但不太清晰的替代方案中,您可以将其init保持原样,但是在子类init中,删除刚刚在 super 目录中创建的约束。
// in NameValueCell.m, in the initWithStyle method, before creating constraints
[self removeConstraints:self.constraints];  // then ...
NSDictionary *views = @{ // and so on...

我不会将此替代方法称为最佳(甚至是好的)实践,但是我认为它应该有效。

10-08 13:57