菜鸟教程小白 发表于 2022-12-12 10:47:42

ios - 如何让 UITableView 标题的这个简单布局使用 AutoLayout 工作?


                                            <p><p>我很惭愧发布此消息,但我变得绝望。</p>

<p>谈到自动布局,我是个菜鸟。这主要是因为我的应用程序中有近 60 个不同的屏幕。为什么要改变有效的方法?无论如何,我不使用 XIBs/NIBs/Storyboards,因为任何时候我需要对应用程序范围的 UI 进行更改,我都必须修复一堆东西。相反,我有自己的一组 UIViewController 子类。其中一个只有一个 UITableView,很像 UITableViewController。我可以在睡梦中制作 UITableViews。</p>

<p>我有一个新屏幕,需要在表格 View 的标题中添加几个按钮。我正在尝试使用 AutoLayout 做得更好,所以我会尽可能地使用它。没有进一步的叙述,这里有一个非常简短的独立示例。</p>

<pre><code>#import &#34;AppDelegate.h&#34;

@interface TestViewController : UIViewController&lt;UITableViewDataSource, UITableViewDelegate&gt;
@property (nonatomic, strong) NSArray *rows;
@end

@implementation TestViewController
- (void) loadView {
    UITableView *tv = [ initWithFrame:[ bounds] style:UITableViewStyleGrouped];
    ;
    ;
    ;
    ;

    UIView *tableHeader = [ init];
    ;
    ;

    UIButton *selectProfileButton = ;
    ;
    ;
    ;
    ;

    UIButton *editProfileButton = ;
    ;
    forState:UIControlStateNormal];
    ;


    UIEdgeInsets padding = UIEdgeInsetsMake(5, 10, 5, 5);

    // select button in NW corner
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top]];
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.left]];
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom]];

    // edit button in NE corner
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top]];
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeRight multiplier:1.0 constant:-padding.right]];
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                                               toItem:tableHeader attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom]];

    // spacing between buttons
    [tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                               toItem:editProfileButton attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-10.0]];
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [ count]; }

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = ;
    if (!cell) {
      cell = [ initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@&#34;cell&#34;];
      ;
    }

    [ setText:[ objectAtIndex:]];

    return cell;
}

@end

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [ initWithFrame:[ bounds]];

    TestViewController *test = [ init];
    ];
    [ setRootViewController:test];

    self.window.backgroundColor = ;
    ;
    return YES;
}
@end
</code></pre>

<p>不幸的是,在运行时我得到了这个:</p>

<pre><code>2014-07-11 13:18:48.502 TestTableHeader *** Assertion failure in -, /SourceCache/UIKit_Sim/UIKit-2935.137/UIView.m:8794
2014-07-11 13:18:48.505 TestTableHeader *** Terminating app due to uncaught exception &#39;NSInternalInconsistencyException&#39;, reason: &#39;Auto Layout still required after executing -layoutSubviews. UITableView&#39;s implementation of -layoutSubviews needs to call super.&#39;
*** First throw call stack:
(
    0   CoreFoundation                      0x017ed1e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x0156c8e5 objc_exception_throw + 44
    2   CoreFoundation                      0x017ed048 + + 136
    3   Foundation                        0x0114c4de - + 116
    4   UIKit                               0x0029ba38 - + 567
    5   libobjc.A.dylib                     0x0157e82b - + 70
    6   QuartzCore                        0x03c5845a - + 148
    7   QuartzCore                        0x03c4c244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    8   QuartzCore                        0x03c583a5 - + 160
    9   UIKit                               0x0035dae3 - + 304
    10UIKit                               0x00273aa7 - + 5212
    11UIKit                               0x00272646 - + 82
    12UIKit                               0x00272518 - + 117
    13UIKit                               0x002725a0 - + 67
    14UIKit                               0x0027163a __57-_block_invoke + 120
    15UIKit                               0x0027159c - + 400
    16UIKit                               0x002722f3 - + 870
    17UIKit                               0x002758e6 - + 449
    18UIKit                               0x0034fb77 - + 180
    19UIKit                               0x0026b474 - + 591
    20UIKit                               0x0026b5ef - + 312
    21UIKit                               0x0026b86b - + 49
    22UIKit                               0x002763c8 - + 65
    23TestTableHeader                     0x00002dfa - + 890
    24UIKit                               0x0022614f - + 309
    25UIKit                               0x00226aa1 - + 1810
    26UIKit                               0x0022b667 - + 824
    27UIKit                               0x0023ff92 - + 3517
    28UIKit                               0x00240555 - + 85
    29UIKit                               0x0022d250 _UIApplicationHandleEvent + 683
    30GraphicsServices                  0x037e2f02 _PurpleEventCallback + 776
    31GraphicsServices                  0x037e2a0d PurpleEventCallback + 46
    32CoreFoundation                      0x01768ca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
    33CoreFoundation                      0x017689db __CFRunLoopDoSource1 + 523
    34CoreFoundation                      0x0179368c __CFRunLoopRun + 2156
    35CoreFoundation                      0x017929d3 CFRunLoopRunSpecific + 467
    36CoreFoundation                      0x017927eb CFRunLoopRunInMode + 123
    37UIKit                               0x0022ad9c - + 840
    38UIKit                               0x0022cf9b UIApplicationMain + 1225
    39TestTableHeader                     0x00002fed main + 141
    40libdyld.dylib                     0x01e34701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
</code></pre>

<p>根据我的阅读,这意味着我缺少一个约束。 UIButtons 有一个固有的大小,所以我只需要设置它们的位置。容器 UIView 将由 UITableView 调整大小,因此无需执行任何操作。 (我什至尝试设置咯咯笑的高度——我没有咯咯笑。)</p>

<p>我在哪里搞砸了?</p>

<p>谢谢!</p>

<p><strong>更新了示例代码和堆栈以提供简短的独立示例。</strong></p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我遇到了同样的问题。我认为这不是由缺少约束引起的。而是因为 <code>UITableView</code> 显然没有正确处理带有自动布局的页眉/页脚。对我有用的解决方法是使用 <code>systemLayoutSizeFittingSize:</code> 方法设置框架:</p>

<pre><code>//initialize tableHeader, add subviews and constraints
CGSize size = ;
tableHeader.frame = (CGRect){.origin = CGPointZero, .size = size};

self.tableView.tableHeaderView = tableHeader;
</code></pre>

<p>请注意,我<strong>没有</strong>将 <code>translatesAutoresizingMaskIntoConstraints</code> 设置为 <code>NO</code>。 </p>

<p>另外,您似乎还没有添加所有需要的约束。您只定位按钮,但您的 tableHeader 不知道如何计算其 <em>自己的</em> 宽度和高度。您可能需要使 <code>selectProfileButton</code>(或其他按钮)的底部等于 <code>tableHeader</code> 的底部,并在按钮之间添加(最小)水平间距。<br/>
另外,据我所知,UITableView 将扩展 <code>tableHeader</code> 的宽度,而不考虑任何约束。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何让 UITableView 标题的这个简单布局使用 AutoLayout 工作?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/24686899/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/24686899/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何让 UITableView 标题的这个简单布局使用 AutoLayout 工作?