使用UITableView部分标题的自动布局问题

Eri*_*len 13 objective-c uitableview ios autolayout

我正在和一个人合作UITableViewController.我有一个项目表,如果用户进行更多编辑,用户可以删除这些项目.当他进入编辑模式时,我想显示一个标题,提供删除所有项目的选项.同时,它应该显示一个标签,提供有关使用空间的信息.如果设备进入横向模式,我希望自动调整大小.据我所知,我需要使用autolayout来做到这一点.

我本来喜欢UIView在Storyboard中设计标题,但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];
}
Run Code Online (Sandbox Code Playgroud)

我在适当时使用此代码插入节标题:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

魔法发生在- headerView方法中.UIView *如果需要,它返回a ,从缓存中获取它.它添加了按钮和标签,然后放入约束.我在故事板中使用了这些相同的约束,我没有遇到任何问题.

- (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;
}
Run Code Online (Sandbox Code Playgroud)

现在,一切都很美好.按钮保持恒定大小(因为拥抱和压缩阻力高于标签),标签将更改其文本以适应可用空间.它在旋转设备时调整大小.垂直居中似乎在标签上,但我现在愿意忽略它.

但是,当我第一次设置节标题时,我收到一个恼人的自动布局警告.

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.
Run Code Online (Sandbox Code Playgroud)

我的第一个想法是将返回的UIView属性更改translatesAutoresizingMaskIntoConstraintsNO.当我这样做时,我会发生崩溃而不是警告.不完全是一种改进.

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.'
Run Code Online (Sandbox Code Playgroud)

有没有人建议如何摆脱警告?

Eri*_*len 0

我尝试使用的解决方法是跳过节标题内容并直接转到tableHeaderView. 我已经editing用这个替换了我的财产:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    if (editing)
        self.tableView.tableHeaderView = [self headerView];
    else
        self.tableView.tableHeaderView = nil;
}
Run Code Online (Sandbox Code Playgroud)

它的动画效果不如节标题那么好,但现在就可以了。

这并没有真正解决实际问题(因此是“解决方法”),所以我不会接受它作为解决方案。