tldr; Auto constrains appear to break on push segue and return to view for custom cells

Edit:我提供了一个github示例项目,展示了发生的错误

应用程序的标题依赖于应用程序的标题,我需要为应用程序创建不同的标题行长度.单元格正确加载到视图中,但如果我按单元格将帖子按推式顺序加载到包含WKWebView的视图中,您可以看到,如屏幕截图所示,单元格会立即移动到错误的位置.当通过UINavigationController的"后退"按钮加载视图时,也可以查看该视图.

在这个特殊的例子中,我按下了最后一个单元格,标题是"我在巴黎拍的两个朋友",所有内容都正确加载.然后,如下一个屏幕截图所示,在加载第二个视图的背景中,由于未知原因,这些单元格都向上移动.然后,当我加载回视图时,你可以看到屏幕稍微向上移动,我实际上无法滚动到显示的任何下方.这似乎是随机的,就像其他测试一样,当视图加载回来时,底部单元格下的空白不会消失.

我还附上了一张图片,其中包含了单元格所具有的约束条件.

图片(我需要更多的声誉来提供这个问题的图片,显然,他们在这个imgur相册中):http://imgur.com/a/gY87E

我的代码:

方法,以允许单元格在旋转时正确调整视图的大小:

override func layoutSubviews() {
    super.layoutSubviews()

    self.contentView.layoutIfNeeded()

    // Update the label constaints
    self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.frame.width
    self.detailsLabel.preferredMaxLayoutWidth = self.detailsLabel.frame.width
}

tableview中的代码

override func viewDidLoad() {
    super.viewDidLoad()

    // Create and register the custom cell
    self.tableView.estimatedRowHeight = 56
    self.tableView.rowHeight = UITableViewAutomaticDimension
}

创建单元格的代码

    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    if let cell = tableView.dequeueReusableCellWithIdentifier("LinkCell", forIndexPath: indexPath) as? LinkTableViewCell {

        // Retrieve the post and set details
        let link: Link = self.linksArray.objectAtIndex(indexPath.row) as Link

        cell.titleLabel.text = link.title
        cell.scoreLabel.text = "\(link.score)"
        cell.detailsLabel.text = link.stringCreatedTimeIntervalSinceNow() + " ago by " + link.author + " to /r/" + link.subreddit

        return cell
    }

    return nil
}

If you require any more code or information please ask and I shall provide what is necessary

谢谢你的帮助!

推荐答案

这种行为的问题是,当你按下一个segue时,tableView将调用estimatedHeightForRowAtIndexPath来显示可见单元格,并将单元格高度重置为默认值.这发生在viewWillDisappear电话之后.如果你回到TableView,所有可见的单元格都被弄乱了..

我用estimatedCellHeightCache解决了这个问题.我只是简单地将这段代码添加到cellForRowAtIndexPath方法中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    // put estimated cell height in cache if needed
    if (![self isEstimatedRowHeightInCache:indexPath]) {
        CGSize cellSize = [cell systemLayoutSizeFittingSize:CGSizeMake(self.view.frame.size.width, 0) withHorizontalFittingPriority:1000.0 verticalFittingPriority:50.0];
        [self putEstimatedCellHeightToCache:indexPath height:cellSize.height];
    }
    ...
}

现在,您必须按照以下步骤实施estimatedHeightForRowAtIndexPath:

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self getEstimatedCellHeightFromCache:indexPath defaultHeight:41.5];
}

Configure the Cache

将此属性添加到您的.h文件:

@property NSMutableDictionary *estimatedRowHeightCache;

实施放置/获取/重置的方法..缓存:

#pragma mark - estimated height cache methods

// put height to cache
- (void) putEstimatedCellHeightToCache:(NSIndexPath *) indexPath height:(CGFloat) height {
    [self initEstimatedRowHeightCacheIfNeeded];
    [self.estimatedRowHeightCache setValue:[[NSNumber alloc] initWithFloat:height] forKey:[NSString stringWithFormat:@"%d", indexPath.row]];
}

// get height from cache
- (CGFloat) getEstimatedCellHeightFromCache:(NSIndexPath *) indexPath defaultHeight:(CGFloat) defaultHeight {
    [self initEstimatedRowHeightCacheIfNeeded];
    NSNumber *estimatedHeight = [self.estimatedRowHeightCache valueForKey:[NSString stringWithFormat:@"%d", indexPath.row]];
    if (estimatedHeight != nil) {
        //NSLog(@"cached: %f", [estimatedHeight floatValue]);
        return [estimatedHeight floatValue];
    }
    //NSLog(@"not cached: %f", defaultHeight);
    return defaultHeight;
}

// check if height is on cache
- (BOOL) isEstimatedRowHeightInCache:(NSIndexPath *) indexPath {
    if ([self getEstimatedCellHeightFromCache:indexPath defaultHeight:0] > 0) {
        return YES;
    }
    return NO;
}

// init cache
-(void) initEstimatedRowHeightCacheIfNeeded {
    if (self.estimatedRowHeightCache == nil) {
        self.estimatedRowHeightCache = [[NSMutableDictionary alloc] init];
    }
}

// custom [self.tableView reloadData]
-(void) tableViewReloadData {
    // clear cache on reload
    self.estimatedRowHeightCache = [[NSMutableDictionary alloc] init];
    [self.tableView reloadData];
}

Swift相关问答推荐

WWDC Swift并发会话中的厨房服务示例令人困惑

在Swift中initt()完成后运行一个函数

如何在Swift中获得与Python相同的HMAC—SHA512签名?

try 在小部件内部读取核心数据的SwiftUI总是返回空吗?

从任务中打印

在SwiftUI中使用ForEach循环来显示字典项的键和值在Form视图中

为什么 XUIView 中的 Binding 看不到更新后的值?

ConfirmationDialog取消swiftui中的错误

Swift 并发:@MainActor 对象上的通知回调

SwiftUI:异步网络请求后@State 值不更新

(SwiftLint)如果有正文,如何编写规则(可能是自定义),在{之后总是\n(换行)?

如何将使用\u{ea12}创建的 Swift 字符串转换回其十六进制值/字符串ea12?

找不到目标AAA的 SPM 工件 - 仅限 Xcode 13.3

Swift - 如何更新多目录中的对象

如何有条件地格式化 SwiftUI 代码

如何使被拖动的对象成为前景(foreground)对象

subscribeOn 和 observeOn 的顺序重要吗?

如何以编程方式读取 wkwebview 的控制台日志(log)

如何在 SwiftUI 中以编程方式滚动列表?

Swift 中的可选数组与空数组