- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我们有选择地使用自动布局约束,主要是定位与可编辑字段元素(通常是 UITextView、UITextField)相关的标签。然而,由于为这些字段实现了自动布局,每当我们卸载 View 、取消分配等时,我们都会看到一个令人讨厌的异常和崩溃。异常是在它试图在卸载 View 之前从 View 中删除约束时发生的。
我们的 View / Controller 层次结构是这样的:
UITableViewController (plain style, but with cell appearance to mimic grouped style)
--> UITableViewCell
----> UIViewController (container for editable form)
------> UICollectionViewController (editable form)
--------> UICollectionViewCell
-----------> UIViewController (editable field)
--------------> UILabel (field label) **HAS CONSTRAINTS**
--------------> UITextView / UITextField (field value) **HAS CONSTRAINTS**
很多时候,当上层表格单元格被释放/替换/重新加载时,我们会看到一个巨大的异常,然后在它试图释放/卸载其中的 View 层次结构时崩溃。
我试图通过捕获异常(没有帮助)并在解除分配/卸载之前(在 viewWillDisappear:
中)强制删除受影响 View 和所有 subview 的所有约束来减轻崩溃,它似乎没有帮助。我什至试图一个一个地消除这些约束,看看是否有一个特别是导致问题的原因,但是当我们调用 removeConstraint:
时,所有这些约束都崩溃了。或 removeConstraints:
在准备消失的容器上。
我很困惑!这是我们的异常的一个片段——大约有 3000 行被删掉了,所以如果您需要更多,请尽管询问。
Exception while deallocating view: { Rows:
0x18911270.posErrorMarker == 4 + 1*0x18911270.negError + 1*0x189112f0.marker + -1*0x189113f0.negError + 1*0x189113f0.posErrorMarker + 1*0x18911a60.marker + -0.5*0x1892dae0.negError + 0.5*0x1892dae0.posErrorMarker + 1*0x18951520.negError + -1*0x18951520.posErrorMarker + -0.5*0x18958090.negError + 0.5*0x18958090.posErrorMarker
0x189112b0.negError == 12 + 1*0x189112b0.posErrorMarker + -1*0x189112f0.marker + 1*0x189113f0.negError + -1*0x189113f0.posErrorMarker + -1*0x18911a60.marker + 1*0x18925530.marker + 0.5*0x1892dae0.negError + -0.5*0x1892dae0.posErrorMarker + 1*0x1893e080.marker + 0.5*0x18958090.negError + -0.5*0x18958090.posErrorMarker + 1*0x18963640.marker
0x18911370.negError == 9 + -1*0x189112f0.marker + 1*0x18911370.posErrorMarker + 1*0x18925530.marker + 1*0x1892dae0.negError + -1*0x1892dae0.posErrorMarker + 1*0x1893e080.marker + 1*0x18963640.marker
0x189113b0.slackMarker == 2 + -1*0x189107d0.marker + 1*0x18910b90.negError + -1*0x18910b90.posErrorMarker +
........ EXPLETIVES DELETED .........
UITableView:0xca2b000.contentHeight == 36 + 1*0xc221c00.marker
UITableView:0xca2b000.contentWidth == 704 + 1*0xc239470.marker
UITableView:0xca2b000.minX == 0 + 1*0xc2a23f0.marker + -0.5*0xc2a2590.marker
UITableView:0xca2b000.minY == 0 + 1*0xc2a25d0.marker + -0.5*0xc2a2630.marker
UITableViewCellContentView:0x18ab13d0.Height == 174 + 1*0x18abd4f0.marker
UITableViewCellContentView:0x18ab13d0.Width == 704 + 1*0x18abd470.marker
........ EXPLETIVES DELETED .........
<NSAutoresizingMaskLayoutConstraint:0x18988bc0 h=-&- v=-&- UIView:0x18911e50.midY == UIView:0x1892d0c0.midY> Marker:0x18988bc0.marker
<NSAutoresizingMaskLayoutConstraint:0x18994b40 h=-&- v=-&- UIView:0xc4a6fb0.midX == UIView:0xc4b4990.midX> Marker:0x18994b40.marker
<NSAutoresizingMaskLayoutConstraint:0x18998480 h=-&- v=-&- UIView:0x18915180.width == UIView:0xc4c5970.width> Marker:0x18998480.marker
<NSAutoresizingMaskLayoutConstraint:0x18aae320 h=--& v=--& TapSectionalTableViewCell:0x18a3d270.midX == + 352> Marker:0x18aae320.marker
<NSAutoresizingMaskLayoutConstraint:0x18aae410 h=--& v=--& H:[TapSectionalTableViewCell:0x18a3d270(704)]> Marker:0x18aae410.marker
<NSAutoresizingMaskLayoutConstraint:0x18aae450 h=--& v=--& TapSectionalTableViewCell:0x18a3d270.midY == + 144> Marker:0x18aae450.marker
........ EXPLETIVES DELETED .........
<NSAutoresizingMaskLayoutConstraint:0xc2de2f0 h=--& v=--& TapGenericCollectionCell:0xc2ac500.midX == + 499> Marker:0xc2de2f0.marker
<NSAutoresizingMaskLayoutConstraint:0xc2de3b0 h=--& v=--& V:[TapGenericCollectionCell:0xc2ac500(34)]> Marker:0xc2de3b0.marker
<NSAutoresizingMaskLayoutConstraint:0xc2de430 h=-&- v=-&- UIView:0x18953f80.height == UIView:0xc2acb20.height> Marker:0xc2de430.marker
<NSAutoresizingMaskLayoutConstraint:0xc2de520 h=-&- v=-&- UIView:0x18923af0.height == UIView:0xc2ae570.height> Marker:0xc2de520.marker
<NSAutoresizingMaskLayoutConstraint:0xc2de560 h=--& v=--& H:[TapGenericCollectionCell:0xc2ac500(280)]> Marker:0xc2de560.marker
........ EXPLETIVES DELETED .........
<NSContentSizeLayoutConstraint:0xc2f5730 H:[_UIBaselineLayoutStrut:0x18994a30(0)] Hug:250 CompressionResistance:750> Marker:0xc2f5730.posErrorMarker
<NSContentSizeLayoutConstraint:0xc2f5730 H:[_UIBaselineLayoutStrut:0x18994a30(0)] Hug:250 CompressionResistance:750> Marker:0xc2f5730.posErrorMarker
<NSContentSizeLayoutConstraint:0xc2f5770 V:[_UIBaselineLayoutStrut:0x18994a30(18)] Hug:250 CompressionResistance:750> Marker:0xc2f5770.posErrorMarker
internal error. Cannot find an outgoing row head for incoming head UIView:0x189712b0.Width, which should never happen.'
/**** BEGIN Individual Field Controller - This code is from the base individual field controller used in our editable form collection *****/
- (void)viewDidLoad {
[super viewDidLoad];
self.view.clipsToBounds = YES;
self.view.opaque = YES;
CGRect viewFrame = self.view.frame;
viewFrame.size = [self defaultFieldSize];
self.view.frame = viewFrame;
if (self.backgroundColor) {
self.view.backgroundColor = self.backgroundColor;
}
else {
self.view.backgroundColor = [UIColor whiteColor];
}
[self createLabelAndField];
[self setLabelAndFieldContraints];
[self.view addConstraints:self.labelValueConstraints];
[self.view setNeedsUpdateConstraints];
}
- (void)createLabelAndField {
[self removeLabelAndField];
UILabel *label = [[UILabel alloc] init];
label.font = self.labelFont;
label.textColor = self.labelColor;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.textAlignment = NSTextAlignmentLeft;
label.adjustsFontSizeToFitWidth = NO;
label.numberOfLines = 0;
if (self.backgroundColor) {
label.backgroundColor = self.backgroundColor;
}
else {
label.backgroundColor = [UIColor whiteColor];
}
[self.view addSubview:label];
self.label = label;
/// EXAMPLE valueView initialization from a subclass that handles long text
TapEditableTextView *textView = [[TapEditableTextView alloc] init];
if (self.hasLabelOverValue) {
textView.shouldMimicTextField = NO;
}
else {
textView.shouldMimicTextField = YES;
}
textView.delegate = self;
textView.keyboardType = UIKeyboardTypeDefault;
textView.font = self.valueFont;
textView.textColor = self.valueColor;
textView.textAlignment = NSTextAlignmentLeft;
textView.normalBackgroundColor = self.backgroundColor;
textView.editable = NO;
textView.textLines = self.textLines;
self.valueTextView = textView;
self.valueView = textView;
[self.view addSubview:textView];
}
- (void)removeLabelAndField {
[self clearConstraints];
if (self.label) {
[self.label removeFromSuperview];
self.label = nil;
}
if (self.valueView) {
[self.valueView removeFromSuperview];
self.valueView = nil;
}
}
- (void)clearConstraints {
if (self.isViewLoaded && self.labelValueConstraints) {
[self.view removeConstraints:self.labelValueConstraints];
}
self.labelValueConstraints = nil;
self.labelToValueHorizConstraint = nil;
self.valueWidthConstraint = nil;
}
// This is called in our field's viewDidLoad, after we've created our label and valueView (UITextField, UITextView, etc)
- (void)setLabelAndFieldContraints {
[self clearConstraints];
self.labelValueConstraints = [NSMutableArray array];
self.label.translatesAutoresizingMaskIntoConstraints = NO;
self.valueView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint = nil;
constraint = [NSLayoutConstraint
constraintWithItem:self.label attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeLeft
multiplier:1.0f constant:self.labelValueGap];
constraint.priority = UILayoutPriorityRequired;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.label attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeTop
multiplier:1.0f constant:0];
constraint.priority = 550;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.label attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeBottom
multiplier:1.0f constant:0];
constraint.priority = 400;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.valueView attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeTop
multiplier:1.0f constant:0];
constraint.priority = UILayoutPriorityRequired;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.valueView attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeBottom
multiplier:1.0f constant:0];
constraint.priority = 499;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.valueView attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeRight
multiplier:1.0f constant: -(kDisclosureWidth + self.labelValueGap) ];
constraint.priority = 901;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.valueView attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationGreaterThanOrEqual
toItem:self.label attribute:NSLayoutAttributeTrailing
multiplier:1.0f constant:self.labelValueGap];
constraint.priority = UILayoutPriorityDefaultHigh + 1;
[self.labelValueConstraints addObject:constraint];
self.labelToValueHorizConstraint = constraint;
constraint = [NSLayoutConstraint
constraintWithItem:self.label attribute:NSLayoutAttributeBaseline
relatedBy:NSLayoutRelationEqual
toItem:self.valueView attribute:NSLayoutAttributeBaseline
multiplier:1.0f constant:0.f];
constraint.priority = 600;
[self.labelValueConstraints addObject:constraint];
constraint = [NSLayoutConstraint
constraintWithItem:self.valueView attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeWidth
multiplier:(1.f - self.labelWidthPercentage) constant:0];
constraint.priority = 305;
[self.labelValueConstraints addObject:constraint];
self.valueWidthConstraint = constraint;
[self setCompressionAndHuggingForLabelView:self.label];
[self setCompressionAndHuggingForValueView:self.valueView];
}
- (void)setCompressionAndHuggingForLabelView:(UILabel *)labelView {
if (!labelView) {
return;
}
[labelView setContentCompressionResistancePriority:510 forAxis:UILayoutConstraintAxisHorizontal];
[labelView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
[labelView setContentHuggingPriority:450 forAxis:UILayoutConstraintAxisHorizontal];
[labelView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
}
- (void)setCompressionAndHuggingForValueView:(UIView *)valueView {
if (!valueView) {
return;
}
[valueView setContentCompressionResistancePriority:509 forAxis:UILayoutConstraintAxisHorizontal];
[valueView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
[valueView setContentHuggingPriority:300 forAxis:UILayoutConstraintAxisHorizontal];
[valueView setContentHuggingPriority:650 forAxis:UILayoutConstraintAxisVertical];
}
/****** END Individual Field Controller ******/
最佳答案
我与一位 Apple 工程师就这次崩溃进行了一次(广泛的)对话。
以下是两个最可能的原因:
您有一个无效的约束,例如 view1.left = view2.left + 20
其中 view2
出乎意料地为零,或者乘数为 0。请务必仔细(和三次)检查您的约束以确保它们是正确的。以下是有问题的约束的 2 个示例:
// The first constraint would be a problem if view2 were nil
[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeBottom multiplier:1 constant:20];
// The second constraint is a problem because the 0 multiplier causes view2 to be "lost"
[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeBottom multiplier:0 constant:5];
您遇到了内部 Foundation 自动布局引擎中与浮点精度累积损失相关的错误。当您崩溃时,您可以通过在控制台中的(大)异常日志中搜索非常小(几乎为零)的 float 来了解这种情况:
< <505:-7.45058e-08>*PWPlotLegendEntryView:0x600000582be0.Height{id: 34609} +
(在控制台输出中搜索 e-
以查找类似这样的小数字。)该数字(在本例中为 -7.45058e-08
)表示内部引擎求解约束时该特定时间点的系数。在这种情况下,这个数字应该正好是 0,但是由于自动布局引擎使用 float 进行计算的方式,它变成了一个非常小的负数,而不是把一切都搞砸了。如果您能在输出中找到这样的数字,就知道您遇到了这个错误。
您如何解决这个问题?
更改您添加(激活)约束的顺序最终可能会改变内部引擎中的计算顺序,结果可能会导致此问题消失,因为数学已完成,不会造成任何问题的精度损失。
当您更改了 View 的内容压缩阻力或内容拥抱优先级时,此问题似乎会更频繁地出现,因此请尝试注释掉执行此操作的任何代码以查看它是否导致此错误发生,或重新排序在您的约束设置代码中更早或更晚发生。
关于我的具体案例的更多细节:
我在 iOS 上遇到了这个崩溃。重现它的步骤很有趣:
经过大量试验和错误后,我能够将问题隔离到一个具体的事情上:为 UIImageView
设置内容压缩阻力和拥抱优先级在每个 TableView 单元格中。在这种情况下, ImageView 在单元格内使用自动布局进行定位,为了实现正确的布局, ImageView 需要恰好是其固有内容大小(其图像的大小)。
这是有问题的代码:
// Inside of the UITableViewCell's updateConstraints method...
[self.imageView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.imageView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
删除上面的代码并用 2 个约束(在 Required 优先级)替换它以将 ImageView 的宽度和高度固定为图像的大小实现了相同的结果,但避免了崩溃。这是替换代码(使用 PureLayout ):
[self.imageView autoSetDimensionsToSize:self.imageView.image.size];
我还发现,只需将有问题的 4 行移动到我的约束设置代码中的不同位置即可解决问题,大概是因为这充分改变了计算顺序以防止有问题的精度损失。
关于ios - AutoLayout:removeFromSuperview/removeConstraints 抛出异常并严重崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17688370/
我确信这是一些愚蠢的错误,但在过去的一个小时里我试图从我的 super View 中删除 subview ,但没有成功。 在我第一次观看时 UIViewController *helpView = [
我不知道如何描述正常场景,调用removeFromSuperview时会导致0.3%崩溃。 这是跟踪: Exception Type: SIGSEGV Exception Codes: SEGV_AC
我在 tvOS 项目中有此代码 var loader: UIViewController! 。 。 . override func viewDidLoad() { super.viewDidL
我有一个带有后退按钮的页面,可以将我带到收件箱。我在 viewWillDisappear 中执行此操作 - -(void)viewWillDisappear:(BOOL)animated { [sup
我添加了多张图片并缩放显示它们。由于内存大小有限,我应该尝试删除其中一些已经通过 removeFromSuperview 看到的内容。我的问题是,当我尝试缩放时,所选图像被 removeFromSup
我有一个从 xib 加载的 UIView 子类,如下所示: // The xib custom view private var view: UIView! override init(frame:
我有以下类来添加和删除事件指示器 View : import Foundation import UIKit class ViewControllerUtils { var container: UI
另一个让我头疼的问题。我以编程方式创建了一个 UIButton。它的唯一目的是站在另一个已按下半秒钟的按钮之上。底部按钮是图片,顶部按钮是垃圾桶。您可以在这里看到我正在尝试做的事情:我有一张图片,要删
我在用 Objective-C 编程对象时有一个小问题。我有一个即将完成的应用程序,一切正常。我的问题是我将我的对象设置为 nil 并在适当的时候释放它们。 但这足够了吗?我应该在何时何地使用 rem
我有六个 ImageView ,我这样设置它们: img1 img2 img3 img4 img5 img6 但是当我使用 removeFromSuperview 函数删除 img1 时,其他 Ima
我有一个 MBProgressHUD,我分配如下: self.progressHUD_ = [[[MBProgressHUD alloc] initWithView:self.view] autor
在使用 imagePickerController 选择图像后,我尝试使用 Core Data 从我的 ViewController.swift 中保存一个对象。我在保存时显示带有微调器的 View
我声明了一个名为 var progressBar 的 UIView 变量:UIView? 我用这个函数显示或隐藏 View func showProgressBar(showBar: Bool){ i
我想在询问触摸 ID 时模糊背景,一旦授权成功,viewcontroller 需要可见。但这没有发生。即使授权成功,viewcontroller 仍然模糊。谁能帮我如何解决这个问题? import U
我需要能够从 View 中删除一个按钮并添加一个不同的按钮。我的代码如下所示: -(void)UpdatePromoBanner:(NSString*)value{ [button setTi
我想制作从 subview 返回到 super View 的动画。 我使用以下方式显示 subview : [UIView beginAnimations:@"curlup" context:nil]
我有一个方法,可以对 UIWindow 的一个 subview 进行动画处理,然后使用 removeFromSuperview 将其从 UIWindow 中删除。但是当我将 removeFromSup
我正在尝试使用以下代码从现有 View 中删除图像: -(void) deleteImage:(int)imageID{ //[self.imageArray removeObjectAtIndex:
我目前正在做一个 ipad 项目并找到了这个。所以这是我的结构 我将 uiviewcontroller 子类化为 customizedVC,像这样 @protocol customizedVCDele
我正在使用 GADBannerView 来展示横幅广告。这是我加载广告的方式: override func viewDidAppear(_ animated: Bool) { supe
我是一名优秀的程序员,十分优秀!