只能在viewDidAppear中正确配置UI吗?而不是 viewWillAppear/viewDidLoad?
Can we only configure UI correctly in viewDidAppear? and not in viewWillAppear/viewDidLoad?
我有一个静态 table 视图,其中的单元格具有圆角边框。我在不同的模拟器上进行测试时注意到,虽然我的自动布局约束有效,但边框并不总是正确的宽度。这个特定的屏幕由一个视图控制器和一个包含嵌入式 tableViewController
的 UIView
组成
我做了一些调查,发现边框的宽度实际上取决于故事板的宽度phone。这意味着如果我有一个 iPhone 8 的故事板,8+ 的单元格太短,反之亦然,8+ 的故事板会导致 8 的单元格太长(并延伸出屏幕)。
目前我正在 viewDidLoad 中设置单元格边框,这是我用来配置单元格边框的代码:
- (void)configureCellThree {
//Add Border
CALayer *borderLayer = [CALayer layer];
CGRect borderFrame = CGRectMake(0, 0, (_contentCellThree.frame.size.width), (_contentCellThree.frame.size.height));
[borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
[borderLayer setFrame:borderFrame];
[borderLayer setCornerRadius:_contentCellThree.frame.size.height / 2];
[borderLayer setBorderWidth:1.0];
[borderLayer setBorderColor:[kTextColor2 CGColor]];
// [borderLayer setOpacity:0.5];
[_contentCellThree.layer addSublayer:borderLayer];
}
现在,如果我在 viewDidAppear
中 运行 这段代码,一切都将在两个设备上运行。我在我的主视图控制器中添加了一些日志,以了解事情是如何设置的。
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"VDL - SELF.VIEW = %@", self.view);
NSLog(@"VDL - CONTAINER VIEW = %@", self.profileScrollingContainerView);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"VDA- SELF.VIEW = %@", self.view);
NSLog(@"VDA - CONTAINER VIEW = %@", self.profileScrollingContainerView);
}
我曾怀疑 viewDidLoad 使用的是情节提要中的大小信息,而不是视图本身(这似乎不对)。此日志记录证实了这一点。如果我查看负责显示我的 table 视图的 UIView
,当故事板设置为 8+ 时,它具有以下框架属性:X = 0, Y = 349, W = 414, H = 338
。现在让我们看看日志记录的结果:
VDL - SELF.VIEW = <UIView: 0x7fa545401f10; frame = (0 0; 375 667);
VDL - CONTAINER VIEW = <UIView: 0x7fa545401b50; frame = (0 349; 414 338);
VDA- SELF.VIEW = <UIView: 0x7fa545401f10; frame = (0 64; 375 603);
VDA - CONTAINER VIEW = <UIView: 0x7fa545401b50; frame = (0 285; 375 269);
因此,当加载视图时,table视图获取有关视图大小的错误信息。当 viewDidAppear
被调用时,它具有正确的视图大小并且将正常工作。我的问题是我不想在我的 viewDidAppear 中调用初始化代码。
I read here that I should be putting my UI Geometry code into the viewWillAppear
但是我试过了,我遇到了同样的问题。
VWA - CONTAINER VIEW = <UIView: 0x7fec04d97700; frame = (0 349; 414 338);
为了巩固我的问题,如何在视图具有 loaded/appeared 之前获取视图的属性,以便我可以正确设置我的 UI?
我读到我需要子类化 UIView
并可能使用 setFrame
但是我真的不知道我将如何真正去做这件事。
原来我用错了方法。 I found this question which solved my whole issue. 基本上,如果您需要执行 UI 计算(例如添加自定义视图),您应该在 -(void)viewDidLayoutSubviews
中执行它们。此方法在视图计算出其所有大小和约束后调用,因此您在此处所做的任何操作都将使用视图的正确属性执行!
子类 UITableViewCell
并实现 layoutSubviews
,即参见 docs:
"Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly."
我有一个静态 table 视图,其中的单元格具有圆角边框。我在不同的模拟器上进行测试时注意到,虽然我的自动布局约束有效,但边框并不总是正确的宽度。这个特定的屏幕由一个视图控制器和一个包含嵌入式 tableViewController
UIView
组成
我做了一些调查,发现边框的宽度实际上取决于故事板的宽度phone。这意味着如果我有一个 iPhone 8 的故事板,8+ 的单元格太短,反之亦然,8+ 的故事板会导致 8 的单元格太长(并延伸出屏幕)。
目前我正在 viewDidLoad 中设置单元格边框,这是我用来配置单元格边框的代码:
- (void)configureCellThree {
//Add Border
CALayer *borderLayer = [CALayer layer];
CGRect borderFrame = CGRectMake(0, 0, (_contentCellThree.frame.size.width), (_contentCellThree.frame.size.height));
[borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
[borderLayer setFrame:borderFrame];
[borderLayer setCornerRadius:_contentCellThree.frame.size.height / 2];
[borderLayer setBorderWidth:1.0];
[borderLayer setBorderColor:[kTextColor2 CGColor]];
// [borderLayer setOpacity:0.5];
[_contentCellThree.layer addSublayer:borderLayer];
}
现在,如果我在 viewDidAppear
中 运行 这段代码,一切都将在两个设备上运行。我在我的主视图控制器中添加了一些日志,以了解事情是如何设置的。
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"VDL - SELF.VIEW = %@", self.view);
NSLog(@"VDL - CONTAINER VIEW = %@", self.profileScrollingContainerView);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"VDA- SELF.VIEW = %@", self.view);
NSLog(@"VDA - CONTAINER VIEW = %@", self.profileScrollingContainerView);
}
我曾怀疑 viewDidLoad 使用的是情节提要中的大小信息,而不是视图本身(这似乎不对)。此日志记录证实了这一点。如果我查看负责显示我的 table 视图的 UIView
,当故事板设置为 8+ 时,它具有以下框架属性:X = 0, Y = 349, W = 414, H = 338
。现在让我们看看日志记录的结果:
VDL - SELF.VIEW = <UIView: 0x7fa545401f10; frame = (0 0; 375 667);
VDL - CONTAINER VIEW = <UIView: 0x7fa545401b50; frame = (0 349; 414 338);
VDA- SELF.VIEW = <UIView: 0x7fa545401f10; frame = (0 64; 375 603);
VDA - CONTAINER VIEW = <UIView: 0x7fa545401b50; frame = (0 285; 375 269);
因此,当加载视图时,table视图获取有关视图大小的错误信息。当 viewDidAppear
被调用时,它具有正确的视图大小并且将正常工作。我的问题是我不想在我的 viewDidAppear 中调用初始化代码。
I read here that I should be putting my UI Geometry code into the viewWillAppear
但是我试过了,我遇到了同样的问题。
VWA - CONTAINER VIEW = <UIView: 0x7fec04d97700; frame = (0 349; 414 338);
为了巩固我的问题,如何在视图具有 loaded/appeared 之前获取视图的属性,以便我可以正确设置我的 UI?
我读到我需要子类化 UIView
并可能使用 setFrame
但是我真的不知道我将如何真正去做这件事。
原来我用错了方法。 I found this question which solved my whole issue. 基本上,如果您需要执行 UI 计算(例如添加自定义视图),您应该在 -(void)viewDidLayoutSubviews
中执行它们。此方法在视图计算出其所有大小和约束后调用,因此您在此处所做的任何操作都将使用视图的正确属性执行!
子类 UITableViewCell
并实现 layoutSubviews
,即参见 docs:
"Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly."