关于 UITableViewCell 重用的问题

2017-03-10 23:00:00 +08:00
 abellee

我在做一个类似于微信朋友圈一样的,复杂的 UITableViewCell

在 UITableViewCell 的init(style: UITableViewCellStyle, reuseIdentifier: String?)里,我先创建好所有要用的控制,比如头像、昵称、内容、图片的容器等。

然后通过一个 setModal 的方法去设置每个 cell 不同的数据, setModal 会在 cellForRowAt 里调用,

而 setModal 里会根据图片的情况显示或隐藏图片的容器。同时更新所有相关视图 AutoLayout 的 top

内容有些只有图片,有些只有文字内容,而有些同时拥有文字跟图片,开始的一屏没问题,往下滚动后,新出来的 cell 也没什么问题,

但当重新往上滚的时候,重新出来的上面的 cell 布局乱了。

我用的是 SnapKit ,乱了布局的 cell 报了Unable to simultaneously satisfy constraints的错。

我检查了我的代码,在 setModal 里,如果有要显示的内容,我就新 makeConstraints ,而一般都是新加一个 top 的约束,如果不需要显示,就把缓存了的 top 约束 deactivate ,并 isHidden=true 掉。

所以我在怀疑,是不是 UITableViewCell 的重用问题, UITableViewCell 的重用不是拿缓存里的 cell 来用的吗?

如果一个 cell 我先用过了,并设置了图片、文字的视图是显示状态的,下一次被调用的时候,他们应该也是显示的,

所以我需要根据内容再做一次显示 /隐藏的动作。那文字呢?我的内容是通过 attributedText 设置的,第一次加载 的时候是正确的,但先往下滚,再往上滚的时候,就不对了,文字的框明显就高了,所以原来对的约束逻辑,就会被“尝试打破约束”这样的错。是不是有什么办法能让显示内容的 label 高度也刷新一下?

而且我还作了另一种尝试,就是把可能会发生隐藏或显示的视图的约束,在setModal里全部重新做一遍, 就是根据数据,如果这个视图是隐藏的,我就直接removeConstraints,下次如果显示,我也先removeConstraints 然后再makeConstraints 把全部约束重新加一遍,显示是对了,但还是会报“尝试打破约束”的打,不知道到底是哪不对

import UIKit
import SnapKit

class CircleCell: UITableViewCell {
var avatar                      : UIView!;
var nickname                    : UILabel!;
var downArrow                   : UILabel!;
var timeLabel                   : UILabel!;
var contentLabel                : UILabel!;
var likeBtn                     : UIButton!;
var commentBtn                  : UIButton!;
var expandLabel                 : UILabel!;
var imageBox                    : ImageCell!;
var pageBox                     : PageCell!;

var contentTopConstraint     : Constraint?;
var expandTopConstriaint     : Constraint?;
var imageBoxTopConstrint     : Constraint?;

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier);
    self.selectionStyle = .none;
    
    self.setUp();
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

fileprivate func setUp(){
    self.contentView.layer.shouldRasterize = true;
    self.contentView.isOpaque = true;
    self.layer.shouldRasterize = true;
    self.isOpaque = true;
    
    avatar = UIView();
    avatar.isUserInteractionEnabled = true;
    avatar.backgroundColor = .red;
    
    nickname = UILabel();
    nickname.sizeToFit();
    nickname.numberOfLines = 1;
    nickname.font = UIFont.boldSystemFont(ofSize: Dimens.COMMON_FONT_SIZE);
    nickname.textColor = Colors.MainYellow;
    
    expandLabel = UILabel();
    expandLabel.sizeToFit();
    expandLabel.numberOfLines = 1;
    expandLabel.textColor = Colors.MainYellow;
    expandLabel.isUserInteractionEnabled = true;
    expandLabel.font = UIFont.systemFont(ofSize: Dimens.COMMON_FONT_SIZE);
    
    contentLabel = UILabel();
    contentLabel.numberOfLines = 0;
    contentLabel.font = UIFont.systemFont(ofSize: Dimens.COMMON_FONT_SIZE);
    contentLabel.textColor = Colors.MAIN_BLACK;
    contentLabel.backgroundColor = .brown;
    
    downArrow = UILabel();
    downArrow.sizeToFit();
    downArrow.textAlignment = .right;
    let arrowStr = FontAwesome.icon("fa-angle-down");
    let arrowAttribute = NSMutableAttributedString(string: arrowStr);
    let arrowFont = UIFont(name: Fonts.FontAwesome, size: Dimens.MATERIAL_ICON_SIZE);
    arrowAttribute.addAttribute(NSFontAttributeName, value: arrowFont!, range: NSMakeRange(0, 1));
    arrowAttribute.addAttribute(NSForegroundColorAttributeName, value: Colors.COLOR9ea1ab, range: NSMakeRange(0, 1));
    downArrow.attributedText = arrowAttribute;
    downArrow.isUserInteractionEnabled = true;
    
    timeLabel = UILabel();
    timeLabel.sizeToFit();
    timeLabel.numberOfLines = 1;
    timeLabel.font = UIFont.systemFont(ofSize: Dimens.SECOND_TITLE_FONT_SIZE);
    timeLabel.textColor = Colors.COLOR9ea1ab;
    timeLabel.backgroundColor = .yellow;
    
    imageBox = ImageCell();
    pageBox = PageCell();
    
    likeBtn = UIButton();
    likeBtn.contentEdgeInsets = UIEdgeInsetsMake(0.01, 0, 0.01, 0);
    
    commentBtn = UIButton();
    commentBtn.contentEdgeInsets = UIEdgeInsetsMake(0.01, 0, 0.01, 0);
    self.contentView.addSubview(self.avatar);
    self.contentView.addSubview(self.nickname);
    self.contentView.addSubview(self.downArrow);
    self.contentView.addSubview(self.timeLabel);
    self.contentView.addSubview(self.commentBtn);
    self.contentView.addSubview(self.likeBtn);
    self.contentView.addSubview(self.contentLabel);
    self.contentView.addSubview(self.expandLabel);
    self.contentView.addSubview(self.imageBox);
    self.contentView.addSubview(self.pageBox);
    layout();
}

fileprivate func layout(){
    self.avatar.snp.makeConstraints { [unowned self](make) in
        make.left.top.equalTo(self.contentView).offset(10);
        make.width.height.equalTo(40);
    }
    
    self.downArrow.snp.makeConstraints { [unowned self](make) in
        make.right.equalTo(self.contentView).offset(-10);
        make.centerY.equalTo(self.nickname);
        make.width.equalTo(40);
        make.height.equalTo(self.nickname).offset(10);
    }
    
    self.nickname.snp.makeConstraints { [unowned self](make) in
        make.left.equalTo(self.avatar.snp.right).offset(10);
        make.top.equalTo(self.avatar);
    }
    
    self.contentLabel.snp.makeConstraints{ [unowned self](make) in
        make.left.equalTo(self.nickname);
        make.right.equalTo(self.contentView).offset(-10);
    }
    
    self.expandLabel.snp.makeConstraints{ [unowned self](make) in
        make.left.equalTo(self.contentLabel);
    }
    
    self.imageBox.snp.makeConstraints{ [unowned self](make) in
        make.left.equalTo(self.contentLabel);
        make.right.equalTo(self.contentView);
    }
    
    self.pageBox.snp.makeConstraints{ [unowned self](make) in
        make.left.equalTo(self.imageBox);
        make.right.equalTo(self.contentView).offset(-10);
    }
    
    self.timeLabel.snp.makeConstraints { [unowned self](make) in
        make.left.equalTo(self.nickname);
        make.bottom.equalTo(self.contentView).offset(-10);
    }
    
    self.commentBtn.snp.makeConstraints { [unowned self](make) in
        make.right.equalTo(self.contentView).offset(-10);
        make.centerY.equalTo(self.timeLabel);
    }
    
    self.likeBtn.snp.makeConstraints { [unowned self](make) in
        make.right.equalTo(self.commentBtn.snp.left).offset(-10);
        make.centerY.equalTo(self.timeLabel);
    }
}

func setModel(data: PostStatus, sizeCache: SizeCache){
    //set up avatar
    
    self.nickname.text = data.user!.nickname;

    let content = data.content;
    var showExpand = false;
    var hasContent = false;
    var hasImage = false;
    var hasPage = false;
    if content != "" {
        hasContent = true;
        self.contentLabel.isHidden = false;
        var lines = sizeCache.visibleLines;
        if sizeCache.totalLines <= 12 {
            lines = sizeCache.totalLines;
        }else{
            showExpand = true;
        }
        
        self.contentLabel.text = content;
        self.contentLabel.numberOfLines = lines;
        self.contentLabel.snp.makeConstraints({ [unowned self](make) in
            self.contentTopConstraint = make.top.equalTo(self.nickname.snp.bottom).offset(10).constraint;
        });
        if showExpand {
            self.expandLabel.isHidden = false;
            self.expandLabel.text = "展开";
            self.expandLabel.snp.makeConstraints{ [unowned self](make) in
                self.expandTopConstriaint = make.top.equalTo(self.contentLabel.snp.bottom).offset(10).constraint;
            }
        }else{
            self.expandLabel.isHidden = true;
            self.expandTopConstriaint?.deactivate();
        }
    }else{
        self.contentTopConstraint?.deactivate();
        self.contentLabel.isHidden = true;
        self.expandTopConstriaint?.deactivate();
        self.expandLabel.isHidden = true;
    }

    let arr = [UIImage](repeating: UIImage(), count: data.images.count);
    self.imageBox.update(images: arr);
    if data.images.count > 0 {
        hasImage = true;
        self.imageBox.isHidden = false;
        if hasContent {
            if showExpand {
                self.imageBox.snp.makeConstraints({ [unowned self](make) in
                    self.imageBoxTopConstrint = make.top.equalTo(self.expandLabel.snp.bottom).offset(10).constraint;
                });
            }else{
                self.imageBox.snp.makeConstraints({ [unowned self](make) in
                    self.imageBoxTopConstrint = make.top.equalTo(self.contentLabel.snp.bottom).offset(10).constraint;
                });
            }
        }else{
            self.imageBox.snp.makeConstraints({ [unowned self](make) in
                self.imageBoxTopConstrint = make.top.equalTo(self.nickname.snp.bottom).offset(10).constraint;
            });
        }
    }else{
        self.imageBoxTopConstrint?.deactivate();
        self.imageBox.isHidden = true;
    }

    if let _ = data.game {
        hasPage = true;
        self.pageBox.snp.makeConstraints({ (make) in
            make.height.equalTo(70);
        });
        if hasImage {
            self.pageBox.snp.makeConstraints({ [unowned self](make) in
                make.top.equalTo(self.imageBox.snp.bottom).offset(10);
            });
        }else{
            if hasContent {
                if showExpand {
                    self.pageBox.snp.makeConstraints({ [unowned self](make) in
                        make.top.equalTo(self.expandLabel.snp.bottom).offset(10);
                    });
                }else{
                    self.pageBox.snp.makeConstraints({ [unowned self](make) in
                        make.top.equalTo(self.contentLabel.snp.bottom).offset(10);
                    });
                }
            }else{
                self.pageBox.snp.makeConstraints({ [unowned self](make) in
                    make.top.equalTo(self.nickname.snp.bottom).offset(10);
                });
            }
        }
    }else{
        //TODO: clear content
    }

    self.timeLabel.text = Time.sinceNow(data.created_at!);
    if hasPage {
        self.timeLabel.snp.makeConstraints({ [unowned self](make) in
            make.top.equalTo(self.pageBox.snp.bottom).offset(10);
        });
    }else{
        if hasImage {
            self.timeLabel.snp.makeConstraints({ [unowned self](make) in
                make.top.equalTo(self.imageBox.snp.bottom).offset(10);
            });
        }else{
            if hasContent {
                if showExpand {
                    self.timeLabel.snp.makeConstraints({ [unowned self](make) in
                        make.top.equalTo(self.expandLabel.snp.bottom).offset(10);
                    });
                }else{
                    self.timeLabel.snp.makeConstraints({ [unowned self](make) in
                        make.top.equalTo(self.contentLabel.snp.bottom).offset(10);
                    });
                }
            }
        }
    }
    
    let likeStr = FontAwesome.icon("fa-thumbs-o-up");
    let likeAttribute = NSMutableAttributedString(string: "\(likeStr) 0");
    let likeFont = UIFont(name: Fonts.FontAwesome, size: Dimens.COMMON_TITLE_FONT_SIZE);
    let commonFont = UIFont.systemFont(ofSize: Dimens.COMMON_TITLE_FONT_SIZE);
    var numStr = "\(data.like_num)";
    var numNum = numStr.characters.count;
    likeAttribute.addAttribute(NSFontAttributeName, value: likeFont!, range: NSMakeRange(0, 1));
    likeAttribute.addAttribute(NSFontAttributeName, value: commonFont, range: NSMakeRange(1, numNum + 1));
    likeAttribute.addAttribute(NSForegroundColorAttributeName, value: Colors.COLOR9ea1ab, range: NSMakeRange(0, numNum + 2));
    
    let likeHighlightedAttribute = NSMutableAttributedString(string: "\(likeStr) 0");
    likeHighlightedAttribute.addAttribute(NSFontAttributeName, value: likeFont!, range: NSMakeRange(0, 1));
    likeHighlightedAttribute.addAttribute(NSFontAttributeName, value: commonFont, range: NSMakeRange(1, numNum + 1));
    likeHighlightedAttribute.addAttribute(NSForegroundColorAttributeName, value: Colors.COLOReeeeee, range: NSMakeRange(0, numNum + 2));
    
    likeBtn.setAttributedTitle(likeAttribute, for: UIControlState());
    likeBtn.setAttributedTitle(likeHighlightedAttribute, for: .highlighted);
    
    let commentStr = FontAwesome.icon("fa-commenting-o");
    let commentAttribute = NSMutableAttributedString(string: "\(commentStr) 0");
    let commentFont = UIFont(name: Fonts.FontAwesome, size: Dimens.COMMON_TITLE_FONT_SIZE);
    numStr = "\(data.comment_num)";
    numNum = numStr.characters.count;
    commentAttribute.addAttribute(NSFontAttributeName, value: commentFont!, range: NSMakeRange(0, 1));
    commentAttribute.addAttribute(NSFontAttributeName, value: commentFont!, range: NSMakeRange(1, numNum + 1));
    commentAttribute.addAttribute(NSForegroundColorAttributeName, value: Colors.COLOR9ea1ab, range: NSMakeRange(0, numNum + 2));
    commentAttribute.addAttribute(NSBaselineOffsetAttributeName, value: 1, range: NSMakeRange(0, 1));
    
    let commentHighlightedAttribute = NSMutableAttributedString(string: "\(commentStr) 0");
    commentHighlightedAttribute.addAttribute(NSFontAttributeName, value: commentFont!, range: NSMakeRange(0, 1));
    commentHighlightedAttribute.addAttribute(NSFontAttributeName, value: commentFont!, range: NSMakeRange(1, numNum + 1));
    commentHighlightedAttribute.addAttribute(NSForegroundColorAttributeName, value: Colors.COLOReeeeee, range: NSMakeRange(0, numNum + 2));
    commentHighlightedAttribute.addAttribute(NSBaselineOffsetAttributeName, value: 1, range: NSMakeRange(0, 1));
    commentBtn.setAttributedTitle(commentAttribute, for: UIControlState());
    commentBtn.setAttributedTitle(commentHighlightedAttribute, for: .highlighted);
}

deinit {
    Log.verbose("\(type(of: self)) deinit");
}

}

4080 次点击
所在节点    iOS
15 条回复
kera0a
2017-03-10 23:20:07 +08:00
重用肯定要考虑 显示了 A 内容的,被拿去显示 B 了。
建议你将需要显示的内容 分成多个类别,每个类别的显示样式都是一样的,然后分配不同的重用标识符。

另外 make 只是会替换相同的约束,
例如上一次设置了 left right top ,这次又重新设置 left right bottom ,则就会有 left right top bottom 四条约束。
如果想重新设置约束,需要使用 remake 。

代码太长懒得看,但看描述和报错就知道应该是这个问题

题外话,写代码最怕的就是将各种情况揉合写在一起,尽量分开写,给接手项目的后人一点活路😄
kera0a
2017-03-10 23:24:49 +08:00
@kera0a 上面关于 make 行为描述需要扩展说一下, 替换只会是相等的两条约束会替换,(替换这词用的不好)
例如 旧约束 a.top = b.top , make 新约束 a.top = b.top . 只有一条约束。

但如果约束不等,则会有两条
例如 旧约束 , a.top = b.top 然后再 make 新约束 a.top = c.top

总之想重新布局,用 remake 重设所有约束吧
abellee
2017-03-10 23:27:43 +08:00
@kera0a
是这样的 一个 cell 里有 头像 昵称 文字 展开 图片 以及时间 开始的时候我是分成了两个,一个是专门显示文字的,一个是有图片的,两种 cell ,但是需求是 除了头像 昵称 及时间,其它都可能隐藏 /显示,所以即使分成两个,也避免不了上面的问题,所以现在我干脆就弄一起。

再一个是 我查了文档是说,如果我先 make 了 left right top ,我想再新增加一个约束,是用 make ,但是如果是想更新 left right top 这三者,我应该是用 updateConstraints 吧?
再就是 remake 实际也是先 remove 再 make ,那我先 removeConstraints 再 makeConstraints 应该是一样的吧?
abellee
2017-03-10 23:29:14 +08:00
@kera0a 我不知道是不是 remake 跟先 remove 再 make 是不一样的?
我试了 remove 再 make 显示是正常的,但还是会报错。一定要用 remake 吗?
abellee
2017-03-10 23:32:13 +08:00
@kera0a 我现在改了一种方式,就是在 setModal 里,开始就把缓存里的约束,也就是上一个 cell 可能已经设置了的约束 deactivate 掉,怎么滚都显示对了,然后还是报下面的错

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<SnapKit.LayoutConstraint:0x7faac0d64be0@CircleCell.swift#110 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.UIView:0x7faac0e43ce0.left == UITableViewCellContentView:0x7faac0c34920.left + 10.0>",
"<SnapKit.LayoutConstraint:0x7faac0d664c0@CircleCell.swift#110 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.UIView:0x7faac0e43ce0.top == UITableViewCellContentView:0x7faac0c34920.top + 10.0>",
"<SnapKit.LayoutConstraint:0x7faac0d68df0@CircleCell.swift#111 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.UIView:0x7faac0e43ce0.width == 40.0>",
"<SnapKit.LayoutConstraint:0x7faac0d6f9f0@CircleCell.swift#122 UILabel:0x7faac0e3a1e0.left == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.UIView:0x7faac0e43ce0.right + 10.0>",
"<SnapKit.LayoutConstraint:0x7faac0d53ac0@CircleCell.swift#123 UILabel:0x7faac0e3a1e0.top == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.UIView:0x7faac0e43ce0.top>",
"<SnapKit.LayoutConstraint:0x7faac0d6d680@CircleCell.swift#127 UILabel:0x7faac0e3a360.left == UILabel:0x7faac0e3a1e0.left>",
"<SnapKit.LayoutConstraint:0x7faac0d62de0@CircleCell.swift#136 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.left == UILabel:0x7faac0e3a360.left>",
"<SnapKit.LayoutConstraint:0x7faac0d6e210@CircleCell.swift#137 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.right == UITableViewCellContentView:0x7faac0c34920.right>",
"<SnapKit.LayoutConstraint:0x7faac0d702e0@CircleCell.swift#147 UILabel:0x7faac0e3ec10.bottom == UITableViewCellContentView:0x7faac0c34920.bottom - 10.0>",
"<NSLayoutConstraint:0x7faac0d77800 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7faac0c34920(375)]>",
"<NSLayoutConstraint:0x7faac0d77ae0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7faac0c34920(87.22)]>",
"<SnapKit.LayoutConstraint:0x7faac0f29370@ImageCell.swift#60 UIView:0x7faac0f300d0.height == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.width * 0.333333343267441 - 10.0>",
"<SnapKit.LayoutConstraint:0x7faac0f3b760@ImageCell.swift#78 UIView:0x7faac0f300d0.top == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.top>",
"<SnapKit.LayoutConstraint:0x7faac0f3a8f0@ImageCell.swift#84 UIView:0x7faac0f300d0.bottom == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.bottom>",
"<SnapKit.LayoutConstraint:0x7faac0f3d570@CircleCell.swift#226 \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.top == UILabel:0x7faac0e3a1e0.bottom + 10.0>",
"<SnapKit.LayoutConstraint:0x7faac0f20f50@CircleCell.swift#270 UILabel:0x7faac0e3ec10.top == \U00c1\U00c6\U00c4\U00ca\U220f\U220f.ImageCell:0x7faac0e445d0.bottom + 10.0>"
)

Will attempt to recover by breaking constraint
<SnapKit.LayoutConstraint:0x7faac0f3a8f0@ImageCell.swift#84 UIView:0x7faac0f300d0.bottom == 简游.ImageCell:0x7faac0e445d0.bottom>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
abellee
2017-03-10 23:48:38 +08:00
解决了:
最后报的那个错是说一堆的约束想打破图片容器里某一个约束,这里可能是我想多了,
就是在处理 UIScrollView 或 UITableViewCell 的 contentView 的时候,我会把最后一个视图的 bottom 约束到 contentView 的 bottom ,以告知 contentView 该怎么拉伸,
而 ImageCell 实际就是一个 UIView ,我也做了这样的处理,反而出错了,我直接把这条约束去掉就 ok 了
Elethom
2017-03-10 23:49:31 +08:00
我很好奇是不是大多數工程師寫 auto layout 都不會用 constraint priority 、 content hugging priority 和 content compression resistance priority 。對於大多數可變佈局的情況,只要保持固定的 constraints 在默認 priority ,降低不固定的 constraints 的 priority ,再相應地設定一下 content 的 hugging 和 compression resistance 屬性就足夠了,並不需要根據內容不同分別設定一套不同的 constraints 。

另外,和 Android 不同的是, hidden views 也會參與佈局,你可以試試看 remove from superview 。

(沒看代碼,如有猜錯請無視)
abellee
2017-03-10 23:54:47 +08:00
@Elethom 惭愧,真心不是很熟 priority 在这方面的应用,我查下资料看看。或者你有没好一点的资料分享下看看,先谢过了。
Elethom
2017-03-11 00:12:25 +08:00
@abellee
其實很簡單,就是在不同的 constraints 產生衝突的時候優先滿足最高 priority 的, priority 較低的那些則被忽略。至於 content , hugging 就是壓縮內容, compression resistance 則是避免壓縮內容。例如要實現在固定空間內並排顯示標題和時間,就可以將時間 label 在橫向上的 compression resistance priority 設定為 required ,這樣就可以保證時間永遠被完整顯示,而過長的標題則會被截斷超長的部份。而 hugging 屬性則可以使內容變少時容器也自動收縮。這些通常與包含 greater than 和 less than 的 constraints 一起使用。
abellee
2017-03-11 00:49:22 +08:00
@Elethom
hugging 跟 compression resistance 这两个在 SnapKit 里有的吗?我就看到一个 priority
还是通过自己去定义这两个,比如 hugging 是 500 , compression resistance 是 700 这样?
Elethom
2017-03-11 01:17:51 +08:00
@abellee
這是原生 methods ,直接看 iOS 的文檔。
loveuqian
2017-03-11 01:44:45 +08:00
少年为什么不用 xib
abellee
2017-03-11 02:30:19 +08:00
@loveuqian 一样有这些问题吧
laoyur
2017-03-11 09:24:02 +08:00
@abellee #13 用 xib 的时候,至少在冲突的时候就告诉你了,然后一般会自动提示你修改 priority
abellee
2017-03-11 23:51:29 +08:00
@laoyur 已经放弃用原生的 改成 asdk 了☹️☹️

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/346584

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX