Ios 具有`NSLayoutConstraint'的内存泄漏`
我有一个简单的布局,带有连接两个视图的约束,并将该约束存储在强属性中 我的期望是,在删除其中一个视图后,约束仍将存在,但它将变为非活动状态。但事实并非如此,我的应用程序因异常而崩溃 幸运的是,我能够重现这个问题。我附上视图控制器的源代码。您可以将其粘贴到使用“单视图应用程序”模板创建的新项目中 要再现问题,请在删除其中一个视图之前和之后打印约束描述。有一次,约束没有被移除,代码也正常工作(但只发生了一次)。通过调试器,我可以检查我删除的视图是否也没有解除分配,而它已经没有层,因此它的某些部分已经解构。事情发生后,我注释掉了Ios 具有`NSLayoutConstraint'的内存泄漏`,ios,objective-c,memory-leaks,autolayout,Ios,Objective C,Memory Leaks,Autolayout,我有一个简单的布局,带有连接两个视图的约束,并将该约束存储在强属性中 我的期望是,在删除其中一个视图后,约束仍将存在,但它将变为非活动状态。但事实并非如此,我的应用程序因异常而崩溃 幸运的是,我能够重现这个问题。我附上视图控制器的源代码。您可以将其粘贴到使用“单视图应用程序”模板创建的新项目中 要再现问题,请在删除其中一个视图之前和之后打印约束描述。有一次,约束没有被移除,代码也正常工作(但只发生了一次)。通过调试器,我可以检查我删除的视图是否也没有解除分配,而它已经没有层,因此它的某些部分已经
printConstraintDescriptionButtouchedupInside
的实现,并在RemoveViewButtonCouchedupInside
中设置断点。当调试器在第二次按下按钮后暂停应用程序时,约束不再存在
是否不允许持有对NSLayoutConstraint
实例的强引用?我在文档中没有找到该信息
使用Xcode版本10.1(10B61)编译,运行iOS模拟器iPhone SE 12.1。在运行iOS 12.1.3(16D5032a)和11.2.2(15C202)的物理设备上,相同的逻辑(但不在独立代码段中)失败。使用Xcode 9.4.1版编译不会改变任何东西
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) UIView* topView;
@property (strong, nonatomic) UIView* bottomView;
@property (strong, nonatomic) NSLayoutConstraint* constraint;
@property (strong, nonatomic) UIButton* removeViewButton;
@property (strong, nonatomic) UIButton* printConstraintDescriptionButton;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.topView = [UIView new];
self.topView.backgroundColor = [UIColor grayColor];
self.topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.topView];
self.bottomView = [UIView new];
self.bottomView.backgroundColor = [UIColor grayColor];
self.bottomView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.bottomView];
self.removeViewButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.removeViewButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.removeViewButton setTitle:@"Remove View"
forState:UIControlStateNormal];
[self.removeViewButton addTarget:self
action:@selector(removeViewButtonTouchedUpInside)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.removeViewButton];
self.printConstraintDescriptionButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.printConstraintDescriptionButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.printConstraintDescriptionButton setTitle:@"Print Constraint Description"
forState:UIControlStateNormal];
[self.printConstraintDescriptionButton addTarget:self
action:@selector(printConstraintDescriptionButtonTouchedUpInside)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.printConstraintDescriptionButton];
NSDictionary* views = @{
@"topView": self.topView,
@"bottomView": self.bottomView,
@"removeViewButton": self.removeViewButton,
@"printConstraintDescriptionButton": self.printConstraintDescriptionButton
};
NSArray<NSString*>* constraints = @[
@"H:|-[topView]-|",
@"H:|-[bottomView]-|",
@"H:|-[printConstraintDescriptionButton]-|",
@"H:|-[removeViewButton]-|",
@"V:|-[topView(==44)]",
@"V:[bottomView(==44)]",
@"V:[printConstraintDescriptionButton]-[removeViewButton]-|"
];
[constraints enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:obj
options:0
metrics:nil
views:views]];
}];
self.constraint = [NSLayoutConstraint constraintWithItem:self.topView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.bottomView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:-8.0];
self.constraint.active = YES;
}
- (void)printConstraintDescriptionButtonTouchedUpInside {
NSLog(@"%@", self.constraint);
}
- (void)removeViewButtonTouchedUpInside {
[self.bottomView removeFromSuperview];
self.bottomView = nil;
}
@end
#导入“ViewController.h”
@界面视图控制器()
@属性(强,非原子)UIView*topView;
@属性(强,非原子)UIView*bottomView;
@属性(强,非原子)NSLayoutConstraint*约束;
@属性(强,非原子)UIButton*removeViewButton;
@属性(强,非原子)UIButton*printConstraintDescriptionButton;
@结束
@实现视图控制器
-(无效)viewDidLoad{
[超级视图下载];
self.topView=[UIView new];
self.topView.backgroundColor=[UIColor grayColor];
self.topView.translatesAutoResizengMaskintoConstraints=否;
[self.view addSubview:self.topView];
self.bottomView=[UIView new];
self.bottomView.backgroundColor=[UIColor grayColor];
self.bottomView.translatesAutoResizengmaskintoConstraints=否;
[self.view addSubview:self.bottomView];
self.removeViewButton=[UIButton Button类型:UIButtonTypeSystem];
self.removeViewButton.translatesAutoResizengMaskintoConstraints=否;
[self.removeViewButton集合标题:@“删除视图”
forState:uicontrol状态正常];
[self.removeViewButton添加目标:self
操作:@选择器(移除ViewButtonToucheDupInside)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.removeViewButton];
self.printConstraintDescriptionButton=[UIButton Button类型:UIButtonTypeSystem];
self.printConstraintDescriptionButton.translatesAutoReshizingMaskintoConstraints=否;
[self.printConstraintDescriptionButton集合标题:@“打印约束说明”
forState:uicontrol状态正常];
[self.printConstraintDescriptionButton添加目标:self
操作:@selector(PrintConstraintDescriptionButtontTouchedupInside)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.printConstraintDescriptionButton];
NSDictionary*视图=@{
@“topView”:self.topView,
@“bottomView”:self.bottomView,
@“removeViewButton”:self.removeViewButton,
@“printConstraintDescriptionButton”:self.printConstraintDescriptionButton
};
NSArray*约束=@[
@“H:|-[topView]-|”,
@“H:|-[bottomView]-|”,
@“H:|-[printConstraintDescriptionButton]-|”,
@“H:|-[removeViewButton]-|”,
@“V:|-[顶视图(=44)]”,
@“V:[底部视图(=44)]”,
@“V:[printConstraintDescriptionButton]-[removeViewButton]-|”
];
[constraints enumerateObjectsUsingBlock:^(NSString*\u非空obj,NSUInteger idx,BOOL*\u非空stop){
[self.view addConstraints:[NSLayoutConstraints Constraints WithVisualFormat:obj
选项:0
指标:零
视图:视图]];
}];
self.constraint=[NSLayoutConstraint constraintWithItem:self.topView
属性:NSLAYUTATTRIBUTEBOTTOM
关系人:NSLayoutRelationEqual
toItem:self.bottomView
属性:NSLAYUTATTRIBUTETOP
乘数:1.0
常数:-8.0];
self.constraint.active=是;
}
-(无效)打印约束描述按钮内部{
NSLog(@“%@”,自约束);
}
-(无效)将ViewButton从内部移除{
[self.bottomView从superview移除];
self.bottomView=nil;
}
@结束
问题不在于约束不再存在。。。问题在于:
NSLog(@"%@", self.constraint);
尝试打印约束的(默认)说明。如果约束未激活,则将抛出EXC_BAD_访问
- (void)printConstraintDescriptionButtonTouchedUpInside {
NSLog(@"self.constraint still exists? %@", self.constraint != nil ? @"Yes" : @"No");
NSLog(@"self.constraint.constant = %0.2f", self.constraint.constant);
if (self.constraint.isActive) {
NSLog(@"self.constraint (default description) %@", self.constraint);
} else {
// this will throw EXC_BAD_ACCESS exception if constraint is not active
// so, don't do it
//NSLog(@"self.constraint (default description) %@", self.constraint);
}
}