【发布时间】:2014-02-07 18:31:37
【问题描述】:
我正在使用UITableViewController。我有一个项目表,如果他进行更多编辑,用户可以删除这些项目。当他进入编辑模式时,我想显示一个标题,提供删除所有项目的选项。同时,它应该显示一个标签,提供有关正在使用多少空间的信息。如果设备进入横向模式,我希望它自动调整大小。据我所知,我需要使用自动布局来执行此操作。
我很想在 Storyboard 中设计的 UIView 中设置标题,但 Storyboard 只允许视图控制器,而不是视图。我知道我可以让一个 XIB 文件保存它,但如果可以的话,我宁愿避免这样做。
首先,我重写了editing 属性,以便在编辑模式下重绘表格部分。
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
NSIndexSet *set = [NSIndexSet indexSetWithIndex:0];
[self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
}
我使用此代码在适当的时候插入节标题:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (self.isEditing)
return [self headerView];
else
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (self.isEditing)
return [self headerView].frame.size.height;
else
return 0;
}
魔法发生在- headerView 方法中。它返回一个UIView *,必要时从缓存中获取。它添加按钮和标签,然后放入约束。我在情节提要中使用了这些相同的约束,我没有遇到任何问题。
- (UIView *)headerView
{
if (headerView)
return headerView;
float w = [[UIScreen mainScreen] bounds].size.width;
UIButton *deleteAllButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[deleteAllButton setTitle:@"Delete All" forState:UIControlStateNormal];
CGRect deleteAllButtonFrame = CGRectMake(8.0, 8.0, 30.0, 30); // The autolayout should resize this.
[deleteAllButton setFrame:deleteAllButtonFrame];
deleteAllButton.translatesAutoresizingMaskIntoConstraints = NO;
[deleteAllButton setContentHuggingPriority:252 forAxis:UILayoutConstraintAxisHorizontal];
[deleteAllButton setContentCompressionResistancePriority:751 forAxis:UILayoutConstraintAxisHorizontal];
CGRect textFrame = CGRectMake(47.0, 8.0, 30.0, 30); // The autolayout should resize this.
UILabel *currSizeText = [[UILabel alloc] initWithFrame:textFrame];
currSizeText.text = @"You have a lot of text here telling you that you have stuff to delete";
currSizeText.translatesAutoresizingMaskIntoConstraints = NO;
currSizeText.adjustsFontSizeToFitWidth = YES;
CGRect headerViewFrame = CGRectMake(0, 0, w, 48);
headerView = [[UIView alloc] initWithFrame:headerViewFrame];
//headerView.autoresizingMask = UIViewAutoresizingNone;//UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//headerView.translatesAutoresizingMaskIntoConstraints = NO;
[headerView addSubview:deleteAllButton];
[headerView addSubview:currSizeText];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(deleteAllButton, currSizeText);
[headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[deleteAllButton]-[currSizeText]-|"
options:0
metrics:nil
views:viewsDictionary]];
[headerView addConstraint:[NSLayoutConstraint constraintWithItem:deleteAllButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:headerView
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];
[headerView addConstraint:[NSLayoutConstraint constraintWithItem:currSizeText
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:headerView
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];
return headerView;
}
现在,一切都运行良好。按钮保持恒定大小(因为拥抱和压缩阻力高于标签)并且标签将更改其文本以适应可用空间。当我旋转设备时它会调整大小。标签上的垂直居中似乎偏离了,但我现在愿意忽略它。
但是,当我第一次设置节标题时,我收到了一个恼人的自动布局警告。
2014-02-07 11:25:19.770 ErikApp[10704:70b] Unable to simultaneously satisfy constraints.
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:0xb9a4ad0 H:|-(NSSpace(20))-[UIButton:0xb99e220] (Names: '|':UIView:0xb9a4680 )>",
"<NSLayoutConstraint:0xb9a4bf0 H:[UIButton:0xb99e220]-(NSSpace(8))-[UILabel:0xb99f530]>",
"<NSLayoutConstraint:0xb9a4c20 H:[UILabel:0xb99f530]-(NSSpace(20))-| (Names: '|':UIView:0xb9a4680 )>",
"<NSAutoresizingMaskLayoutConstraint:0xa2d1680 h=--& v=--& H:[UIView:0xb9a4680(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xb9a4bf0 H:[UIButton:0xb99e220]-(NSSpace(8))-[UILabel:0xb99f530]>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
我的第一个想法是将返回的UIView 属性translatesAutoresizingMaskIntoConstraints 更改为NO。当我这样做时,我会遇到崩溃而不是警告。不完全是一种改进。
2014-02-07 10:49:13.041 ErikApp[10597:70b] *** Assertion failure in -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2903.23/UIView.m:8540
2014-02-07 10:49:13.383 ErikApp[10597:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'
有没有人建议如何消除警告?
【问题讨论】:
-
仅供参考,您可以将标题视图直接放在情节提要中的
UITableViewController上。只需将视图拖到表格顶部即可。 -
这听起来是个好主意@TimothyMoose。不过我确实试过了。它不像我现在的方法那样动画,即使它消失了,也会留下空白。
-
你的“UITableView header”实际上是一个section header。为了清楚起见,最好将其称为节标题。
-
很公平。我已编辑问题以反映这一点。
-
仅供参考,当您使用自动布局时,您不应手动设置组件的框架。
标签: ios objective-c uitableview autolayout