2015-02-23 103 views
-1

我剛遇到一個關於奇怪的UITableViewCell子類佈局的奇怪問題。 我已經在代碼中配置了所有這些東西的UITableViewCell子類。UITableViewCell子類的奇怪佈局約束

  • iPhone 5S和下部WORK PERFECT

enter image description here

  • iPhone 6或加上WRONG :(

enter image description here

我確定這是子類問題。

(lldb) po _tableView 
<UITableView: 0x7fa5db054c00; frame = (0 0; 375 618); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fa5d96649e0>; layer = <CALayer: 0x7fa5d96632a0>; contentOffset: {0, 0}; contentSize: {375, 15552}> 

代碼:

@interface ColorCell : UITableViewCell 

@end 

@implementation ColorCell 

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
    self.background = [UIView new]; 
    self.top   = [UIView new]; 
    self.bottom  = [UIView new]; 

    self.contentView.translatesAutoresizingMaskIntoConstraints = NO; 
    self.background.translatesAutoresizingMaskIntoConstraints = NO; 
    self.top.  translatesAutoresizingMaskIntoConstraints = NO; 
    self.bottom. translatesAutoresizingMaskIntoConstraints = NO; 

    [self.contentView addSubview:self.background]; 
    [self.background addSubview:self.top]; 
    [self.background addSubview:self.bottom]; 

    self.top.backgroundColor  = [UIColor purpleColor]; 
    self.bottom.backgroundColor  = [UIColor blackColor]; 

    } 
    return self; 
} 

- (void)updateConstraints 
{ 
    [super updateConstraints]; 
    if (!self.didSetupConstraints) { 

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_firstColor,_secondColor,_thirdColor,_fourthColor,_fifthColor,_background,_top,_bottom,_title,_stars,_favourites); 

    NSString *format; 
    NSArray *constraintsArray; 
    NSDictionary *metrics = @{@"topHeight":@100.0, @"bottomHeight":@50}; 

    format = @"V:|[_background]|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllCenterX metrics:nil views:viewsDictionary]; 
    [self.contentView addConstraints:constraintsArray]; 

    format = @"H:|[_background]|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:NSLayoutFormatAlignAllCenterX metrics:nil views:viewsDictionary]; 
    [self.contentView addConstraints:constraintsArray]; 

    format = @"V:|[_top(topHeight)][_bottom(bottomHeight)]|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:metrics views:viewsDictionary]; 
    [_background addConstraints:constraintsArray]; 

    format = @"H:|[_bottom]|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:viewsDictionary]; 
    [_background addConstraints:constraintsArray]; 

    format = @"H:|[_top]|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:viewsDictionary]; 
    [_background addConstraints:constraintsArray]; 

    self.didSetupConstraints = YES; 
    } 
} 

感謝。

編輯:

(lldb) po [[UIWindow keyWindow] recursiveDescription] 
<UIWindow: 0x7fa91341ce00; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fa91341b290>; layer = <UIWindowLayer: 0x7fa91341c610>> 
| <UILayoutContainerView: 0x7fa913703e70; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa91343f400>; layer = <CALayer: 0x7fa913702480>> 
| | <UINavigationTransitionView: 0x7fa913621e80; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7fa91361d7e0>> 
| | | <UIViewControllerWrapperView: 0x7fa9159678d0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fa91343f150>> 
| | | | <UIView: 0x7fa913441190; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fa913443820>> 
| | | | | <UITableView: 0x7fa913841400; frame = (0 0; 375 618); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fa91342f520>; layer = <CALayer: 0x7fa913435060>; contentOffset: {0, 0}; contentSize: {375, 15582}> 
| | | | | | <UITableViewWrapperView: 0x7fa913445200; frame = (0 0; 375 618); gestureRecognizers = <NSArray: 0x7fa913440320>; layer = <CALayer: 0x7fa9134319d0>; contentOffset: {0, 0}; contentSize: {375, 618}> 
| | | | | | | <ColorCell: 0x7fa913637230; baseClass = UITableViewCell; frame = (0 600; 375 150); autoresize = W; layer = <CALayer: 0x7fa9136375b0>> 
| | | | | | | | <UITableViewCellContentView: 0x7fa913637630; frame = (0 0; 375 150); gestureRecognizers = <NSArray: 0x7fa913637960>; layer = <CALayer: 0x7fa913637700>> 
| | | | | | | | | <UIView: 0x7fa9136379c0; frame = (0 0; 324 150); layer = <CALayer: 0x7fa913637a90>> 
| | | | | | | | | | <UIView: 0x7fa913638730; frame = (0 0; 324 100); layer = <CALayer: 0x7fa913638800>> 
| | | | | | | | | | | <UIView: 0x7fa913637ab0; frame = (0 0; 0 0); layer = <CALayer: 0x7fa913637b80>> 
| | | | | | | | | | | <UIView: 0x7fa913637ba0; frame = (0 0; 0 0); layer = <CALayer: 0x7fa913637c70>> 
| | | | | | | | | | | <UIView: 0x7fa913637c90; frame = (0 0; 0 0); layer = <CALayer: 0x7fa913637d60>> 
| | | | | | | | | | | <UIView: 0x7fa913637d80; frame = (0 0; 0 0); layer = <CALayer: 0x7fa913637e50>> 
| | | | | | | | | | | <UIView: 0x7fa913637e70; frame = (0 0; 0 0); layer = <CALayer: 0x7fa913637f40>> 
| | | | | | | | | | <UIView: 0x7fa913638820; frame = (0 100; 324 50); layer = <CALayer: 0x7fa9136388f0>> 
| | | | | | | | | | | <UILabel: 0x7fa913637f60; frame = (8 8; 240 34); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fa913636920>> 
| | | | | | | | | | | | <_UILabelContentLayer: 0x7fa9135b5ba0> (layer) 
| | | | | | | | | | | <UIImageView: 0x7fa913638290; frame = (256 25; 17 0); userInteractionEnabled = NO; layer = <CALayer: 0x7fa913638390>> 
| | | | | | | | | | | <UILabel: 0x7fa9136383b0; frame = (281 -100; 35 0); clipsToBounds = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fa913638510>> 

奇點: 如果我刪除self.contentView.translatesAutoresizingMaskIntoConstraints = NO和它的作品完美。但奇怪的問題是提出了限制的警告。

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) 
(
    "<NSLayoutConstraint:0x7fad5b9764e0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fad5b971a20(44)]>", 
    "<NSLayoutConstraint:0x7fad5b976fb0 V:|-(0)-[UIView:0x7fad5b971db0] (Names: '|':UITableViewCellContentView:0x7fad5b971a20)>", 
    "<NSLayoutConstraint:0x7fad5b976db0 V:[UIView:0x7fad5b971db0]-(0)-| (Names: '|':UITableViewCellContentView:0x7fad5b971a20)>", 
    "<NSLayoutConstraint:0x7fad5b9763c0 V:|-(0)-[UIView:0x7fad5b972b70] (Names: '|':UIView:0x7fad5b971db0)>", 
    "<NSLayoutConstraint:0x7fad5b977730 V:[UIView:0x7fad5b972b70(100)]>", 
    "<NSLayoutConstraint:0x7fad5b976410 V:[UIView:0x7fad5b972b70]-(0)-[UIView:0x7fad5b972c60]>", 
    "<NSLayoutConstraint:0x7fad5b9777b0 V:[UIView:0x7fad5b972c60(50)]>", 
    "<NSLayoutConstraint:0x7fad5b977800 V:[UIView:0x7fad5b972c60]-(0)-| (Names: '|':UIView:0x7fad5b971db0)>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fad5b976410 V:[UIView:0x7fad5b972b70]-(0)-[UIView:0x7fad5b972c60]> 

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. 
+1

您關注的是單元格,但我想知道問題是否是tableview本身的約束。它的約束是什麼樣子的?在Xcode中使用新的[查看調試器](https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_6_0.html#//apple_ref/doc/uid/TP40014509-SW7) 6,或運行應用程序,暫停執行,並在'(lldb)'提示符處輸入'po [[UIWindow keyWindow] recursiveDescription]'並查看錶視圖的框架本身是什麼。 – Rob 2015-02-23 16:40:35

+0

您也可以查看'po [[UIWindow keyWindow] _autolayoutTrace]'以確保您的約束沒有任何警告。 – Rob 2015-02-23 16:48:36

+0

@Rob謝謝你的回覆。我只是編輯遞歸描述。 – 2015-02-23 16:51:32

回答

4

因爲這不是編程方式創建你應該不需要self.contentView.translatesAutoresizingMaskIntoConstraints = NO;。此外,您需要在覆蓋的結尾處撥打[super updateConstraints],而不是開頭。編輯包括錯誤(來自下面的評論):這裏發生的是UIView-Encapsulated-Layout-Height是爲自定義單元格創建的iOS 8約束。單元格被創建後,如果約束被修改,您將會得到這個錯誤。有幾種方法來管理它;在這種情況下,我還是要提一下,因爲你只需要添加約束一次,請嘗試添加不在updateConstraints中的約束,而是在initWithStyle:reuseIdentifier中添加約束。

這個問題更加微妙,而iOS8的一個新問題是:在某些時候,你的tableView認爲行高是44,所以它創建了一個約束設置單元格高度爲44的值。然後添加這些約束條件,但tableView不重新計算高度,所以你會得到錯誤。如果像@Rob在上面注意到的那樣,那麼你將高度設置爲44就可以了。它不會解決你的問題是一些約束是告訴tableView高度應該是44,但無論你可以應該設置estimatedRowHeight爲150,因爲這看起來像一個安全的估計,或者如果他們都肯定會是150剛剛設置rowHeight對此。

+0

我以編程方式添加了所有約束。我刪除了'self.contentView.translatesAutoresizingMaskIntoConstraints = NO;'並且完美。但**奇怪的問題是提出了限制的警告。 – 2015-02-23 16:58:05

+0

Autolayout警告通常很奇怪,你可以編輯包含它們的問題。 – 2015-02-23 17:06:59

+0

已編輯和更新。 – 2015-02-23 17:23:46

1

我終於找出了約束警告的原因。

我刪除- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath委託方法和警告消失。

因此,答案是明確的:我不應該做的事約束更新在heightForRowAtIndexPath。相反,我只是返回rowHeight,然後修復問題。

+2

@Rob謝謝sooooo了。你完全正確。我應該接受你們兩個的答案。乾杯! – 2015-02-24 00:12:41