具有自动布局的UITableViewCell子类如何在运行时更改约束优先级

时间:2014-04-17 17:55:37

标签: ios uitableview autolayout

我的故事板中有一个细胞原型 基本上,细胞分为两部分:

  • 文字视图
  • 图片视图

初始化单元格,其值将对象传递给单元格本身。在该方法中,单元格将其元素设置为传递的值 主要思想是根据图像或文本的存在来改变单元格布局。为此,我过度约束UITextViewUIImageView一方面增加了两个具有不同优先级的约束。优先级将根据传递的对象而改变。
enter image description here 例如,UITextView有两条虚线,它们代表具有不同优先级和不同常数值的两个约束。第一个(从LtoR读取)的优先级为910,常数为156,第二个优先级为900,常数为20。
在故事板编辑器中,如果我交换2个优先级,我会在视觉上获得我想要实现的目标。
单元格代码:

- (void) updateConstraints {
   if (self.postObject.timelinePostText && self.postObject.timelinePostMultimedia) {
       self.imageMinusTextViewConstraint.priority = 900;
       self.imagePlusTextViewConstraint.priority = 910;
       self.textViewMinusImageViewConstraint.priority = 900;
       self.textViewPlusImageViewConstraint.priority = 910;

   }
   else if (self.postObject.timelinePostMultimedia) {
       self.imageMinusTextViewConstraint.priority = 910;
       self.imagePlusTextViewConstraint.priority = 900;
   }
   else if (self.postObject.timelinePostText) {
       self.textViewMinusImageViewConstraint.priority = 910;
       self.textViewPlusImageViewConstraint.priority = 900;
   }

   [super updateConstraints];
}



- (void) configureCellWith: (AFTimelinePostObject*) postObject {
    self.postObject = postObject;
    self.userNameLabel.text = postObject.timelinePostOriginalPoster;
    self.dateLabel.text = [[AFTimelinePostObject dateFormatterInternet] stringFromDate:postObject.timelinePostDateObject];
    self.postTitleLabel.text = postObject.timelinePostTitle;
    self.multimediaMediaType = postObject.timelinePostMultimedia ? [self checkMediaTypeAtPath: postObject.timelinePostMultimedia] : kMediaTypeUnknown;
    if (postObject.timelinePostMultimedia && postObject.timelinePostText) {
        [self.postImageView setImageWithURL:[NSURL URLWithString:postObject.timelinePostMultimedia] placeholderImage:nil];
        self.postTextView.text = postObject.timelinePostText;
    }
    else if (postObject.timelinePostMultimedia) {
        [self bringSubviewToFront:self.postImageView];
        [self.postImageView setImageWithURL:[NSURL URLWithString:postObject.timelinePostMultimedia] placeholderImage:nil];
    }
    else if (postObject.timelinePostText) {
        [self bringSubviewToFront:self.postTextView];
        self.postTextView.text = postObject.timelinePostText;
        self.postImageView.image = nil;
    }
    [self setNeedsUpdateConstraints];
    [self updateConstraintsIfNeeded];
    [self setNeedsLayout];
    [self layoutIfNeeded];

}


删除视图不是解决方案,因为单元格被回收,如果需要我应该重新添加它,但是这样我猜想我会错过与回收相关的性能优势。
不幸的是,细胞仍然平均分为文本和图像,而不会根据传递的数据更改其框架 我错过了什么?

2 个答案:

答案 0 :(得分:1)

不要删除约束的视图。而是将您在xib / storyboard中设置的约束连接到代码中的插座,并在constant方法中修改其configureCell值。不要玩优先考虑的事情。根据是否有图像或文本更改常量。

如果您的逻辑仅允许 文本单元格图像单元格,则可以设置两个具有不同标识符的不同单元格并相应地出列。这会简化您在某种程度上配置逻辑。

此外,而不是

[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
[self setNeedsLayout];
[self layoutIfNeeded];

只需致电[self setNeedsLayout];

答案 1 :(得分:1)

好吧,我已经提取了一些小样本,以简化操作。 那里基本上有两个错误:

  1. 优先事项不应该在updateConstraints更新,我仍然试图找到关于这种方法的海豚的一个非常明确的答案,但似乎你应该只在你添加时使用(可能是删除不是约束
  2. 我将 - bringSubViewToFront发送给了错误的父级,正确的是-contentView
  3. 这是正确的代码,感谢@Leo支持我。

    //- (void) updateConstraints {
    //    if (_postObject[TEXT_KEY] && _postObject[IMAGE_NAME_KEY]) {
    //        self.imageMinusTextViewConstraint.priority = 800;
    //        self.imagePlusTextViewConstraint.priority = 999;
    //        self.textViewMinusImageViewConstraint.priority = 800;
    //        self.textViewPlusImageViewConstraint.priority = 999;
    //        
    //    }
    //    else if (_postObject[IMAGE_NAME_KEY]) {
    //        self.imageMinusTextViewConstraint.priority = 999;
    //        self.imagePlusTextViewConstraint.priority = 800;
    //    }
    //    else if (_postObject[TEXT_KEY]) {
    //        self.textViewMinusImageViewConstraint.priority = 999;
    //        self.textViewPlusImageViewConstraint.priority = 800;
    //    }
    //
    //    [super updateConstraints];
    //}
    //
    //
    //- (void) layoutSubviews {
    //    [super layoutSubviews];
    //}
    
    
    
    - (void) configureCellWith: (NSDictionary*) postObject {
        //Configurare gli elmenti già presenti
        self.postObject = postObject;
    
        //Check the presence of some kind of data
        if (postObject[TEXT_KEY] && postObject[IMAGE_NAME_KEY]) {
            self.imageMinusTextViewConstraint.priority = 800;
            self.imagePlusTextViewConstraint.priority = 999;
            self.textViewMinusImageViewConstraint.priority = 800;
            self.textViewPlusImageViewConstraint.priority = 999;
            self.postImageView.image = [UIImage imageNamed:postObject[IMAGE_NAME_KEY]];
            self.postTextView.text = postObject[TEXT_KEY];
    
        }
        else if (postObject[IMAGE_NAME_KEY]) {
            self.imageMinusTextViewConstraint.priority = 999;
            self.imagePlusTextViewConstraint.priority = 800;
            self.postImageView.image = [UIImage imageNamed:postObject[IMAGE_NAME_KEY]];
            self.postTextView.text = nil;
            [self.contentView bringSubviewToFront:self.postImageView];
    
        }
        else if (postObject[TEXT_KEY]) {
            self.textViewMinusImageViewConstraint.priority = 999;
            self.textViewPlusImageViewConstraint.priority = 800;
    
            self.postTextView.text = postObject[TEXT_KEY];
            self.postImageView.image = nil;
            [self.contentView bringSubviewToFront:self.postTextView];
    
        }
    
    //    [self setNeedsLayout];
    //    [self layoutIfNeeded];
    
    
    
    }