UITableView的波涛汹涌滚动没有图像或内容抓取 [英] UITableView choppy scrolling WITHOUT images or content fetching

查看:158
本文介绍了UITableView的波涛汹涌滚动没有图像或内容抓取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我这有它的UITableView从内存中获取数据(已preloaded,没有要求怎么回事,而它正在滚动,一切都装正在layouted视图前)。每个单元有基于文本的一个UITextView和自动布局量动态计算它的高度。细胞是从笔尖加载和重用细胞正常工作(至少我希望如此)。我用UITableViewAutomaticDimension计算行高度的时候,所以我不强迫细胞布局两次像你不得不做此之前的iOS 8。

So I've got this UITableView which gets its data from memory (already preloaded, there are no requests going on while it is scrolling, everything is loaded before the view is being layouted). Each cell has its height dynamically calculated based on the amount of text in a UITextView and Autolayout. The cells are loaded from a Nib and reusing cells is working properly (at least I hope so). I use UITableViewAutomaticDimension when calculating row height, so I do not force cells to layout twice like you had to do that prior to iOS 8.

下面是我填充细胞和计算的高度相关的方法:

Here is the relevant methods where I populate the cells and calculate the heights:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellType = [self reuseIdentifierForIndexPath:indexPath];

    if ([cellType isEqualToString:kLoadingCell])
        return kLoadingCellHeight;
    else if ([cellType isEqualToString:kOfflineCell])
        return kOfflineCellHeight;
    else if ([cellType isEqualToString:kFootprintListHeaderCell])
        return kHeaderCellHeight;
    else if ([cellType isEqualToString:kFootprintCellUnsynced])
        return kUnsyncedCellHeight;
    else if ([cellType isEqualToString:kShowFullTripCell])
        return kShowFullTripCellHeight;
    else if ([cellType isEqualToString:kFootprintOnMapCell])
        return kFootprintOnMapCellHeight;
    else
    {
        return UITableViewAutomaticDimension;
    }
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellType = [self reuseIdentifierForIndexPath:indexPath];

    if ([cellType isEqualToString:kLoadingCell])
        return kLoadingCellHeight;
    else if ([cellType isEqualToString:kOfflineCell])
        return kOfflineCellHeight;
    else if ([cellType isEqualToString:kFootprintListHeaderCell])
        return kHeaderCellHeight;
    else if ([cellType isEqualToString:kFootprintCellUnsynced])
        return kUnsyncedCellHeight;
    else if ([cellType isEqualToString:kShowFullTripCell])
        return kShowFullTripCellHeight;
    else if ([cellType isEqualToString:kFootprintOnMapCell])
        return kFootprintOnMapCellHeight;
    else
    {
        return UITableViewAutomaticDimension;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellType = [self reuseIdentifierForIndexPath:indexPath];

    if ([cellType isEqualToString:kLoadingCell])
    {
        UITableViewCell *loadingCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
        loadingCell.tag = kLoadingCellTag;
        loadingCell.selectionStyle = UITableViewCellSelectionStyleNone;
        loadingCell.backgroundColor = loadingCell.contentView.backgroundColor = [UIColor clearColor];

        UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
        activityIndicatorView.center = CGPointMake(tableView.frame.size.width / 2, 20);
        [loadingCell.contentView addSubview:activityIndicatorView];

        [activityIndicatorView startAnimating];

        return loadingCell;
    }
    else if ([cellType isEqualToString:kOfflineCell])
    {
        FPOfflineCell *offlineCell = [tableView dequeueReusableCellWithIdentifier:kOfflineCell];
        return offlineCell;
    }
    else if ([cellType isEqualToString:kFootprintListHeaderCell])
    {
        FPFootprintListHeaderCell *headerCell = [tableView dequeueReusableCellWithIdentifier:kFootprintListHeaderCell];
        [headerCell.syncButton addTarget:self action:@selector(syncButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        return headerCell;
    }
    else if ([cellType isEqualToString:kFootprintCellUnsynced])
    {
        FPFootprintCellUnsynced *unsyncedCell = [tableView dequeueReusableCellWithIdentifier:kFootprintCellUnsynced];
        unsyncedCell.footprint = self.map.footprintsNonSynced[[self unsyncedFootprintIndexForIndexPath:indexPath]];
        return unsyncedCell;
    }
    else if ([cellType isEqualToString:kShowFullTripCell])
    {
        FPShowFullTripCell *showFullTripCell = [tableView dequeueReusableCellWithIdentifier:kShowFullTripCell];
        return showFullTripCell;
    }
    else if ([cellType isEqualToString:kFootprintOnMapCell])
    {
        FPFootprintOnMapCell *footprintOnMapCell = [tableView dequeueReusableCellWithIdentifier:kFootprintOnMapCell];
        footprintOnMapCell.footprint = self.map.footprints[0];
        return footprintOnMapCell;
    }
    else
    {
        FPFootprint *footprint = self.map.footprints[[self footprintIndexForIndexPath:indexPath]];
        FootprintCell *cell = [tableView dequeueReusableCellWithIdentifier:kFootprintCell];
        cell.titleLabel.text = footprint.name;
        cell.dateLabel.text = footprint.displayDate;
        cell.textView.text = nil;
        if (footprint.text && footprint.text.length > 0) {
            if ([self.readmoreCache[@(footprint.hash)] boolValue]) {
                cell.textView.text = footprint.text;
            } else {
                cell.textView.text = [footprint.text stringByAppendingReadMoreAndLimitingToCharacterCount:300 screenWidth:tableView.frame.size.width];
            }
        } else {
            cell.hasText = NO;
        }
        cell.textView.markdownLinkTextViewDelegate = self;
        [cell.textView setNeedsDisplay];
        cell.isPrivate = footprint.isPrivate;
        [cell.likesAndCommentsView setLikesCount:footprint.likes andCommentsCount:footprint.comments];
        [cell.likesAndCommentsView setLiked:footprint.liked];
        [cell.likesAndCommentsView.likeButton addTarget:self action:@selector(likeButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [cell.likesAndCommentsView.likesTextButton addTarget:self action:@selector(likesTextButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [cell.likesAndCommentsView.commentButton addTarget:self action:@selector(commentButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [cell.likesAndCommentsView.commentsTextButton addTarget:self action:@selector(commentsTextButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [cell.detailButton addTarget:self action:@selector(detailButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [cell.translateButton addTarget:self action:@selector(translateButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        if (footprint.canBeTranslated) {
            cell.translationStatus = footprint.translationState;
            if (footprint.translationState == FPFootprintTranslationStateTranslated) {
                cell.translatedTextView.text = footprint.translatedText;
            }
        } else {
            cell.translationStatus = FPFootprintTranslationStateNotAvailible;
        }
        cell.numberOfImages = 2;

        return cell;
    }
}

这是我的手机:

import UIKit

@objc class FootprintCell: UITableViewCell {

    var translationStatus: FPFootprintTranslationState = .NotTranslated {
        didSet {
            translateButton.hidden = true
            translateLoader.stopAnimating()
            translatedTextView.hidden = true
            translatedTextView.text = nil

            translatedTextView.addConstraint(translatedTextViewHeightConstraint)
            translationButtonHeightConstraint.constant = 0
            loaderHeightConstraint.constant = 0

            switch translationStatus {
            case .NotAvailible:
                break
            case .NotTranslated:
                translateButton.hidden = false
                translationButtonHeightConstraint.constant = translationButtonHeightConstraintConstant
            case .Translating:
                translateLoader.startAnimating()
                loaderHeightConstraint.constant = loaderHeightConstraintConstant
                translatedTextView.text = nil
            case .Translated:
                translatedTextView.hidden = false
                translatedTextView.removeConstraint(translatedTextViewHeightConstraint)
            }
        }
    }

    var isPrivate: Bool = false {
        didSet {
            privacyBar.hidden = !isPrivate
            privacyIcon.image = UIImage(named: isPrivate ? "ic_lock" : "ic_globe")
        }
    }

    var hasText: Bool = true {
        didSet {
            if hasText {
                textView.removeConstraint(textViewHeightConstraint)
            } else {
                textView.addConstraint(textViewHeightConstraint)
            }
        }
    }

    var numberOfImages: Int = 0 {
        didSet {
            if numberOfImages == 0 {
                imagesContainer.subviews.map { $0.removeFromSuperview() }
            } else if numberOfImages == 2 {
                twoImagesContainer = NSBundle.mainBundle().loadNibNamed("FootprintCellTwoImagesContainer", owner: nil, options: nil)[0] as? FootprintCellTwoImagesContainer
                twoImagesContainer?.setTranslatesAutoresizingMaskIntoConstraints(false)
                imagesContainer.addSubview(twoImagesContainer!)
                let views = ["foo" : twoImagesContainer!] as [NSString : AnyObject]
                imagesContainer.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[foo]|", options: .allZeros, metrics: nil, views: views))
                imagesContainer.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[foo]|", options: .allZeros, metrics: nil, views: views))
            }
        }
    }

    @IBOutlet private(set) weak var titleLabel: UILabel!
    @IBOutlet private(set) weak var dateLabel: UILabel!
    @IBOutlet private(set) weak var textView: FPForwardingTextView!
    @IBOutlet private(set) weak var likesAndCommentsView: FPLikesAndCommentsView!
    @IBOutlet private weak var privacyBar: UIView!
    @IBOutlet private weak var privacyIcon: UIImageView!
    @IBOutlet private(set) weak var detailButton: UIButton!
    @IBOutlet private(set) weak var translateButton: UIButton!
    @IBOutlet private weak var translateLoader: UIActivityIndicatorView!
    @IBOutlet private(set) weak var translatedTextView: FPForwardingTextView!
    @IBOutlet private(set) weak var imagesContainer: UIView!

    private(set) var twoImagesContainer: FootprintCellTwoImagesContainer?

    @IBOutlet private weak var translationButtonHeightConstraint: NSLayoutConstraint!
    @IBOutlet private weak var loaderHeightConstraint: NSLayoutConstraint!
    @IBOutlet private var translatedTextViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet private var textViewHeightConstraint: NSLayoutConstraint!

    private var translationButtonHeightConstraintConstant: CGFloat!
    private var loaderHeightConstraintConstant: CGFloat!

    override func awakeFromNib() {
        super.awakeFromNib()

        textView.contentInset = UIEdgeInsets(top: -10, left: -5, bottom: 0, right: 0)
        textView.linkColor = UIColor(fromHexString: "0088CC")

        translatedTextView.contentInset = UIEdgeInsets(top: -10, left: -5, bottom: 0, right: 0)
        translatedTextView.linkColor = UIColor(fromHexString: "0088CC")

        privacyBar.backgroundColor = UIColor(patternImage: UIImage(named: "ic_privacy_bar"))

        translatedTextView.text = nil
        translatedTextView.hidden = true
        translateButton.hidden = true
        translationButtonHeightConstraintConstant = translationButtonHeightConstraint.constant
        loaderHeightConstraintConstant = loaderHeightConstraint.constant
        hasText = true
    }

    func layoutMargins() -> UIEdgeInsets {
        return UIEdgeInsetsZero
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        numberOfImages = 0
        translationStatus = .NotAvailible
        hasText = true
    }

}

FootprintCellTwoImagesContainer FPLikesAndCommentsView 从笔尖加载,目前不包含任何图像或加载任何东西,只是一些自动布局

FootprintCellTwoImagesContainer and FPLikesAndCommentsView are loaded from Nibs and currently do not contain any images or load anything, just some Autolayout.

所以,当整个的tableView被加载并显示在每个单元至少一次(所以应该有足够的细胞再利用)的主要问题是偶数,以后慢慢滚动在单元格边框向上或向下,我得到一个小跳(如5个像素上下)。这发生在每个设备上,即使是6加。

So the main problem is even when the whole tableView is loaded and every cell is displayed at least once (so there should be enough cells to reuse), after SLOWLY scrolling over a cell border up or down, I get a small jump (like 5 pixels up and down). This happens on every device, even on a 6 Plus.

任何想法,问题可能是什么?我希望这不是在xibs的东西与我的约束,至少界面生成器不会抛出警告有...

Any ideas where the problem could be? I hope it is not something with my constraints in the xibs, at least Interface Builder does not throw warnings there ...

推荐答案

我不那么肯定UITableViewAutomaticDimension是表格单元格。从文档...

I'm not so sure UITableViewAutomaticDimension is for table cells. From the documentation...

您返回从当你想的UITableView选择默认值,要求尺寸度量的UITableViewDelegate方法此值。例如,如果您在返回的tableView这个常数:heightForHeaderInSection:或的tableView:heightForFooterInSection :, UITableView的使用,适合从的tableView返回值的高度:titleForHeaderInSection:或的tableView:titleForFooterInSection:(如果标题不为零)

You return this value from UITableViewDelegate methods that request dimension metrics when you want UITableView to choose a default value. For example, if you return this constant in the tableView:heightForHeaderInSection: or tableView:heightForFooterInSection:, UITableView uses a height that fits the value returned from tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: (if the title is not nil).

的tableview细胞没有提到。

No mention of tableview cells.

所以,我做了搜索,发现这个...
在UITableViewAutomaticDimension ...

So I did a search and found this... more discussion on UITableViewAutomaticDimension...

凡说。

将无法正常工作。 UITableViewAutomaticDimension不旨在用于设置行的高度。使用rowHeight和指定你的价值或实现:

所以我认为你可能有错误的。

So I think you may have that wrong.

这篇关于UITableView的波涛汹涌滚动没有图像或内容抓取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆