“使用UITableViewCell子类执行-layoutSubviews之后仍然需要自动布局

使用XCode 4.5和iOS 6,我正在开发一个带有自定义单元格的简单表格视图的应用程序。 我已经在iOS 5和更低版本中做了这么多次,但由于某种原因,新的autoLayout系统给我带来了很多麻烦。

我在IB中设置了我的表格视图和原型单元格,添加了子视图并将它们连接成IBOutlets,然后设置我的委托和数据源。 但是,现在无论何时第一个单元格从cellForRowAtIndexPath获取,我得到以下错误:

***声明失败 – [ShopCell layoutSublayersOfLayer:],/ SourceCache /UIKit_Sim/UIKit-2372/UIView.m:5776

***终止应用程序由于未捕获的exception“NSInternalInconsistencyException”,原因:执行-layoutSubviews后仍然需要自动布局。 ShopCell的-layoutSubviews实现需要调用super。

我没有实现一个-layoutSubviews方法在我的subclassed单元格(ShopCell),甚至当我尝试这样做,并添加超级调用,因为它暗示我仍然得到相同的错误。 如果我从IB中的单元格删除子视图,并将其更改为标准的UITableViewCell,一切都按预期工作,当然我没有数据在我的单元格。

我几乎可以肯定,有一些简单的我错过了,但无法find任何文档或指南来build议我做错了什么。 任何帮助,将不胜感激。

编辑:只是尝试将其更改为IB中的UITableViewCell,并留下所有的子视图,仍然是相同的错误。

我在代码中手动添加约束时遇到了同样的问题。 在代码中,我正在执行以下操作:

 { [self setTranslatesAutoresizingMaskIntoConstraints:YES]; [self addSubview:someView]; [self addSubview:someOtherView]; [self addConstraint:...]; } 

假设

从我可以告诉,问题是,当您禁用translatesAutoresizingMaskIntoConstraints ,UITableViewCell开始使用自动布局,并自然失败,因为layoutSublayersForLayer的底层实现不调用超级。 有人用漏斗或其他工具可以证实这一点。 因为你使用的IB你可能想知道为什么这是一个问题…这是因为使用IB自动禁用translatesAutoresizingMaskIntoConstraints的视图,它添加约束(它会自动添加一个宽度和高度约束在他们的位置)。

我的解决scheme是将所有内容移到contentView

 { [self.contentView addSubview:someView]; [self.contentView addSubview:someOtherView]; [self.contentView addConstraint:...]; } 

我不是100%确定这是否能在Interface Builder中工作,但是如果你把所有的东西都从你的单元中取出(假设你有直接的东西),那么它应该可以工作。 希望这可以帮助你!

显然,UITableViewCell的layoutSubviews实现不会调用超级,这是自动布局的问题。 我有兴趣看看是否将以下类别放入项目中可以修复这些问题。 它帮助了一个testing项目。

 #import <objc/runtime.h> #import <objc/message.h> @implementation UITableViewCell (FixUITableViewCellAutolayoutIHope) + (void)load { Method existing = class_getInstanceMethod(self, @selector(layoutSubviews)); Method new = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews)); method_exchangeImplementations(existing, new); } - (void)_autolayout_replacementLayoutSubviews { [super layoutSubviews]; [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling [super layoutSubviews]; } @end 

当我在表格单元格上使用backgroundView时,我可能会添加这个问题,因为它会作为子视图添加到单元格中(而大多数子视图应该添加到表格单元格的contentView中,这通常会更好)。

注意:这个bug在iOS7中出现了, 我能够删除这个代码,或者至less添加一个运行时检查,以便它只在iOS6上运行。

我有几个月相同的错误。 但是我发现了什么问题。

当我创build一个IB文件时,一个UIView已经被添加了。 如果你使用这个视图,当禁用自动布局时应用程序不会崩溃(但还有其他的问题)。 当您使用自动布局时,您必须在对象库中select正确的视图: UITableViewCell

事实上,你应该总是使用这个项目,因为所有的子视图都被添加到UITableViewCellcontentView中。

就这样。 一切都会好起来的。

我有自定义的UITableViewHeaderFooterView + xib相同的麻烦。

我在这里看到了一些答案,但是我发现在我的自定义页脚视图类中修复了什么实现-layoutSubviews问题:

 -(void)layoutSubviews { [super layoutSubviews]; [self layoutIfNeeded]; // this line is key } 

我看到这是由于在layoutSubviews的实现中修改约束的结果。 将该调用从方法的开头移动到结尾修复问题。

在iOS 7中有相同的问题(iOS 8似乎修复)。 我的解决scheme是在我的viewDidLayoutSubviews方法结束时调用[self.view layoutIfNeeded]

我遇到过同样的问题。 问题在于我创build单元格Xib的方式。 我创build了一个像正常的Xib,只是将默认的“UIView”的types更改为我自定义的UITableViewCell类。 正确的方法是首先删除默认视图,然后将表格视图单元格对象拖到xib上。 更多细节在这里: http : //allplayers.github.io/blog/2012/11/18/Custom-UITableViewCell-With-NIB/

我通过closures自定义表格视图单元格的所有子视图的“Autolayout”来解决这个问题。

在自定义单元格的xib中,select一个子视图并取消选中File Inspector> Interface Builder Document> Use Autolayout

我有一个类似的问题不是在UITableViewCell ,而是在UITableView本身。 因为这是Google的第一个结果,我会在这里发布。 原来, viewForHeaderInSection是问题。 我创build了一个UITableViewHeaderFooterView并将translatesAutoresizingMaskIntoConstraints设置为NO 。 现在来了一个有趣的部分:

IOS 7:

 // don't do this on iOS 7 sectionHeader.translatesAutoresizingMaskIntoConstraints = NO; 

如果我这样做的应用程序崩溃

执行-layoutSubviews之后仍然需要自动布局。 UITableView的-layoutSubviews实现需要调用super。

好吧,我以为你不能在表格视图标题上使用自动布局,只能在子视图上使用。 但是,这不是你后来看到的完整的事实。 总结一下:不要在iOS 7上禁用自动resize掩码。否则,它工作正常。

iOS 8:

 // you have to do this, otherwise you get an auto layout error sectionHeader.translatesAutoresizingMaskIntoConstraints = NO; 

如果我不会使用这个,我会得到以下输出:

无法同时满足约束。

对于iOS 8,您必须禁用标题的自动resize掩码。

不知道为什么这样的行为,但似乎苹果确实在iOS 8中修复了一些东西,自动布局在iOS 7和iOS 8上的工作方式不同。

正如上面的人已经说过,当你创build一个UITableView使用的视图,你必须删除默认创build的视图,并拖动一个UITableViewCell或UITableViewHeaderFooterView作为根视图。 但是,有一种方法可以修复XIB,以免错过了这个部分。 您必须在文本编辑器中打开XIB文件,并在根标记中直接添加/更改属性translatesAutoresizingMaskIntoConstraintsYES

<view contentMode="scaleToFill" horizontalHuggingPriority="1000" id="1" translatesAutoresizingMaskIntoConstraints="YES" customClass="MXWCollapsibleTableHeaderView">

我遇到这个,它似乎与UITableViewCell子类作为原型单元格,具体有其他自定义的UIView子类添加到它们。 我在这里强调“自定义”,因为我已经成功地使用了UIKit子元素的单元格,但是在尝试为我创build的视图创build约束时抛出了错误,抛出了作者问题中提到的错误。

我不得不把我的单元格分成不使用AutoLayout的独立的笔尖。

让我们希望苹果清理这个烂摊子。

我遇到这一个,因为我最初添加一个UIView而不是一个UITableViewCell到一个xib文件。

我通过从我的背景UIImageViewaccessoryView连接器从我的UIButton定制解耦backgroundView连接器,消除了这个错误。 我怀疑这些并不意味着我使用它们的方式。

今天我第一次遇到这个问题。 直到现在,我在使用原型UITableViewCell子类方面还有一些经验,但从来没有遇到过这个问题。 我正在使用的单元格的不同之处在于,我使用了一个IBOutlet来使用-backgroundView来对单元格着色。 我发现,如果我创build了一个新的属性,并且还添加了一个新的UIView,这个UIView扩展了整个单元的范围,这个断言就消失了。 为了validation这是原因,我回到附加这个观点的backgroundViewsockets和断言重新出现。 到目前为止,自从我做了这个改变之后,没有其他问题在子类原型UITableViewCell中使用AutoLayout。

将您的子视图添加到单元格的contentView而不是单元格本身。 所以,而不是:

[self addSubview:someView];

你必须使用

[self.contentView addSubview:someView];

我没有得到任何妥善解决这个问题,但你可以解决它通过使用框架,而不是将translatesAutoresizingMaskIntoConstraints属性设置为否(默认情况下,是的,所以不要设置它)

 CGRect headerViewFrame = CGRectMake(0,0,320,60); //Frame for your header/footer view UIView *tableHeaderView = [[UIView alloc] initWithFrame:headerViewFrame]; tableHeaderView.translatesAutoresizingMaskIntoConstraints = Yes; //Or don't set it at all [self.tableView setTableHeaderView:tableHeaderView]; 

我一直在经历同样的事情。 事实certificate,如果以编程方式从ShopCell .xib / storyboard中添加一个子视图,该子视图使用自动布局作为另一个视图的子视图,则可能会引发该exception,具体取决于您的约束如何configuration。 我的猜测是在IB中创build的约束是以编程方式将视图添加为子视图时产生的麻烦,因为它然后维护来自viewA – > viewB的约束,同时您可以将viewB作为viewC的子视图添加。 你知道了(这句话甚至让我感到困惑)?

在我的情况 – 因为这是非常简单的意见,导致了这个问题 – 我编程创build的意见,而不是在IB。 这解决了它。 您可能会将这些视图提取到其他xib文件并禁用这些视图的自动布局。 我想这会工作。

在某些情况下,这很容易解决布局问题(取决于您的布局)。 在你的UITableView子类中,在awakeFromNib或init中,设置自动识别掩码:

 self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

通过默认设置为UIViewAutoresizingNone

就我而言,

UITableView的自动布局的引用UIImageView被分配给UITableView的backgroundView。

 self.tableView.backgroundView = self.tableBackgroundImageView; 

所以,我从UIView(根视图)中删除了UIImageView for backgroundView,并重置(删除)所有自动布局引用到该UIImageView。 我把这个UIImageView放在UIView(根视图)的外部。 然后分配给代码中的UITableView的backgroundView。

然后修复。

我find了解决办法。

在我的情况下,我创build了故事板的单元格视图(启用自动布局),我定义了我的ViewController.m中的自定义UITableViewCell接口,我必须将接口移动到ViewController.h。

当我使用故事板来创build自定义的UITableViewCell时,我遇到了同样的问题。 幸运的是,我发现这个问题,因为我将accessoryView([UITableViewCell setAccessoryView:])放到我添加到单元格中的UIButton中。

所以它在iOS6上运行时发生在我的项目中。

我释放accessoryView和我的button之间包含自定义单元格之间的sockets。

提案

你不应该使用UITableViewCell的本地元素,并改变它。

这个问题可能是由于忘记在viewDidAppear调用[super viewDidAppear:]造成的,但是我相信这不是唯一的原因。

我有完全相同的问题。 这是我的项目的问题:
当我在Interface Builder上创build自定义的UITableViewCell时,我从Xcode的对象集合窗格中拖动了一个View而不是Table View Cell
作为自定义表格单元格。
如果你处于同样的情况,这里是解决scheme:
删除界面构build器中的视图,确保从对象集合窗格中拖动表视图单元格,并重新创build自定义表格单元格视图。 您可以复制旧视图中的对象并将其粘贴到新的“表格视图单元”的canvas上。

我有一个非常类似的问题,我在Xcode 6,iOS 7 +中设置了表格页脚视图。 解决scheme是以nib文件的格式。 显然它被卡在Xcode 4格式或东西。 将文件设置更改为“打开:Xcode 6.0”(或者默认,就此而言),立即修复它。 偶然发现了这个解决scheme:这让我疯狂,所以我删除了整个文件,并重新创build,显然使用默认设置。 我不知道为什么简单地编辑最新的Xcode中的文件并没有把它转换成Xcode 5+格式,就像它经常发生的那样。

F

我去了同样的问题。 我去了我的DetailViewController并将标识符重命名为UIView。 它以前在UITableView。 它解决了这个问题。 这个问题不一定要在你的DetailViewController中。 它可能在其他任何一个。 尝试将其重命名为尊重的标识符。

我在IB中有一个与静态表格视图单元类似的问题。 其中一个单元格的子视图有一个类被错误地更改为UITextfield的子类。 编译器没有给出任何警告/错误。 但是在运行时,系统无法加载视图控制器,导致上述崩溃。

问题是对子视图布局调用的sorting:

查看

iOS中显示<8

解决scheme:在调用super layoutSubviews之前更改约束

 - (void)layoutSubviews { [self _updateConstraints]; [super layoutSubviews]; } 

我修改了卡尔·林德伯格的答案 ,而不是重写UITableView ,它开始为我工作:

的UITableView + AutoLayoutFix.h

 @interface UITableView (AutoLayoutFix) @end 

的UITableView + AutoLayoutFix.m

 #import <objc/runtime.h> @implementation UITableView (AutoLayoutFix) + (void)load { Method existingMethod = class_getInstanceMethod(self, @selector(layoutSubviews)); Method newMethod = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews)); method_exchangeImplementations(existingMethod, newMethod); } - (void)_autolayout_replacementLayoutSubviews { [super layoutSubviews]; [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling [super layoutSubviews]; } @end 

然后在MyViewController.m我只是导入了类别:

 #import "UITableView+AutoLayoutFix.h" 

我遇到了同样的问题,最后发现原因是我添加了一个约束UITableViewCell,应该是UITableViewCell的contentView 。 当我改变约束时,一切都很好!