【问题标题】:UITableView scrolling is not smooth with multiple custom cells多个自定义单元格的 UITableView 滚动不流畅
【发布时间】:2016-11-03 10:55:15
【问题描述】:

以下是索引路径中行单元格的完整代码——这里的表格视图是多个自定义单元格,应该根据值返回。滚动表格视图滞后很多..我正在使用 YYWebimage 进行图像加载,并且单元格的内容不断变化,需要显示表格视图行高的高度,

- (UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    KVembedLinkTableViewCell* KVCell = [tableView dequeueReusableCellWithIdentifier:@"Link"];

    [KVCell flushCell];
    [KVCell layoutIfNeeded];
    _postDict = [NSMutableDictionary dictionaryWithDictionary:[cardDetailsArray objectAtIndex:indexPath.row]];
    NSLog(@"feedstimeline postdict: %@",_postDict);
    [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
    NSArray *embedlist = [NSArray new];
    embedlist = [_postDict valueForKeyPath:@"recentpost.embedlist"];
    NSArray *medialist = [NSArray new];
    medialist = [_postDict valueForKeyPath:@"recentpost.medialist"];
    KVCell.embededDetails = _postDict;
    KVCell.embedlist = embedlist;

    NSString *discription = [NSString stringWithFormat:@"%@",[_postDict valueForKeyPath:@"recentpost.staticdata.contenttext"]];
    discription = [CVUtilityManager stripEmptyTags:discription];
    KVCell.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
    [KVCell.userDescription setText:discription];
    NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
    KVCell.userDescriptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
    [KVCell laodUserDescription:attr];
    [KVCell.userDescription updateConstraints];
    [KVCell.userDescription setNeedsLayout];
    [KVCell.userDescription layoutIfNeeded];
    [KVCell setLikeDelegate:self];
    NSString *typeOfCardString = cardTypeArray[indexPath.row];
    if ([CVUtilityManager stringIsNull:typeOfCardString]) typeOfCardString =  @"UNKNOWN";
    _typeOfCard = [self defineCardTypeFromType:typeOfCardString];
    switch (_typeOfCard) {

        case VIDEO: {

            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    [KVCell loadVideoDetails:[NSMutableDictionary dictionaryWithDictionary:embedlist[0]]];
                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];

        } break;
        case UNKNOWN:
        case TEXT: {
            [KVCell loadTextWithString];
            KVCell.linkViewHeight.constant = 0;
            KVCell.multiTableViewHeight.constant = 0;
            [KVCell laodCellContents];
            [KVCell.linkContentView layoutIfNeeded];
            [KVCell.linkContentView updateConstraints];
            [KVCell layoutIfNeeded];
            [KVCell setNeedsLayout];
            [KVCell updateConstraints];
            NSLog(@"card type TEXT");
        }break;
        case EMBEDFB: {
            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    NSString *URLFB = [embedlist[0] objectOrNilForKey:@"url"];
                    [KVCell loadFaceBookDetails:[CVUtilityManager neutraliseString:URLFB] withVideoButtonStatus:NO];
                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];

        } break;
        case EMBEDINSTAGRAM: {

            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    NSString *URLINSTA = [embedlist[0] objectOrNilForKey:@"url"];
                    [KVCell loadInstagramDetails:[CVUtilityManager neutraliseString:URLINSTA]];
                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];

        } break;

        case EMBEDPHOTO: {

            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    KVCell.linkViewHeight.constant = 253;
                    [KVCell embedPhoto:[NSMutableDictionary dictionaryWithDictionary:embedlist[0]]];

                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;
            KVCell.multiTableViewHeight.constant = 0;
            KVCell.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCell.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCell.userDescriptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCell laodUserDescription:attr];
            [KVCell.userDescription updateConstraints];
            [KVCell.userDescription setNeedsLayout];
            [KVCell.userDescription layoutIfNeeded];


            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
        } break;
        case KANVZPOST:
        case LINK: {

            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    KVCell.linkViewHeight.constant = 253;
                    [KVCell loadLinkView:[NSMutableDictionary dictionaryWithDictionary:embedlist[0]]];

                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;
            KVCell.multiTableViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];

        } break;
        case SOUND_CLOUD_AUDIO:
        case MULTI_SOUND_CLOUD_AUDIO: {
            NSLog(@"card type MULTI_SOUND_CLOUD_AUDIO");
            if (embedlist.count > 0 ) {
                [KVCell loadAudioLinksWithArray:embedlist];
                KVCell.multiTableViewHeight.constant = embedlist.count * 132.00;
                KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.multiTableViewHeight.constant = 0;
            KVCell.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCell.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCell.userDescriptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCell laodUserDescription:attr];
            [KVCell.userDescription updateConstraints];
            [KVCell.userDescription setNeedsLayout];
            [KVCell.userDescription layoutIfNeeded];

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];


        } break;
        case EMBEDRICH:
        case MULTIPLE_LINK: {
            if (embedlist.count > 0 ) {
                [KVCell loadMultiLinksWithArray:embedlist];
                KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];


        } break;
        case FACEBOOK_VIDEO_CARD: {
            if (embedlist.count > 0 ) {
                if (embedlist[0] != nil) {
                    NSString *URLFB = [embedlist[0] objectOrNilForKey:@"url"];
                    [KVCell loadFaceBookDetails:[CVUtilityManager neutraliseString:URLFB] withVideoButtonStatus:YES];

                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;

            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];

        } break;
        case AUDIO: {
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            KVembedAudio
            * KVCellAUDIO = [tableView dequeueReusableCellWithIdentifier:@"Audio" forIndexPath:indexPath];
            KVCellAUDIO.embededDetails = _postDict;
            [KVCellAUDIO setLikeDelegate:self];
            KVCellAUDIO.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCellAUDIO.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCellAUDIO.userDescrptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCellAUDIO laodUserDescription:attr];
            [KVCellAUDIO.userDescription updateConstraints];
            [KVCellAUDIO.userDescription setNeedsLayout];
            [KVCellAUDIO.userDescription layoutIfNeeded];

            [KVCellAUDIO performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:true];
            [KVCellAUDIO.contentView layoutIfNeeded];
            NSLog(@"card type AUDIO");
            return KVCellAUDIO;
        } break;
        case PHOTO: {
            KVCell.embedlist = medialist;
            if (medialist.count > 0 ) {
                if (medialist[0] != nil) {

                    [KVCell uploadPhoto:[NSMutableDictionary dictionaryWithDictionary:medialist[0]]];

                }else
                    KVCell.linkViewHeight.constant = 0;
            }else
                KVCell.linkViewHeight.constant = 0;
            KVCell.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCell.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCell.userDescriptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCell laodUserDescription:attr];
            [KVCell.userDescription updateConstraints];
            [KVCell.userDescription setNeedsLayout];
            [KVCell.userDescription layoutIfNeeded];
            [KVCell performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
        } break;

        case MULTIPLE_EMBEDPHOTO: {
            NSLog(@"card type MULTIPLE_EMBEDPHOTO");
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            NSArray *mediaList =  [[_postDict objectOrNilForKey:@"recentpost"] objectOrNilForKey:@"embedlist"];
            KVembedPhotoMultiple
            * KVCellPhoto = [tableView dequeueReusableCellWithIdentifier:@"Photo Multiple" forIndexPath:indexPath];
            [KVCellPhoto flushCell];
            KVCellPhoto.embededDetails = _postDict;
            if (mediaList.count>0) {
                [KVCellPhoto loadEmbedPhotos:mediaList];
            }
            [KVCellPhoto setLikeDelegate:self];
            KVCellPhoto.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCellPhoto.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCellPhoto.userDescrptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCellPhoto laodUserDescription:attr];
            [KVCellPhoto.userDescription updateConstraints];
            [KVCellPhoto.userDescription setNeedsLayout];
            [KVCellPhoto.userDescription layoutIfNeeded];

            [KVCellPhoto performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
            [KVCellPhoto.contentView layoutIfNeeded];
            return KVCellPhoto;
        } break;

        case MULTIPLE_PHOTO: {
            NSLog(@"card type MULTIPLE_PHOTO");
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            NSArray *mediaList =  [[_postDict objectOrNilForKey:@"recentpost"] objectOrNilForKey:@"medialist"];
            NSLog(@"mediaList  %@",mediaList);
            KVembedPhotoMultiple
            * KVCellPhoto = ( KVembedPhotoMultiple *)[tableView dequeueReusableCellWithIdentifier:@"Photo Multiple" forIndexPath:indexPath];
            [KVCellPhoto flushCell];
            KVCellPhoto.embededDetails = _postDict;
            if (mediaList.count>0) {
                [KVCellPhoto loadUploadedPhotos:mediaList];
            }
            [KVCellPhoto setLikeDelegate:self];
            KVCellPhoto.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCellPhoto.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCellPhoto.userDescrptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCellPhoto laodUserDescription:attr];
            [KVCellPhoto.userDescription updateConstraints];
            [KVCellPhoto.userDescription setNeedsLayout];
            [KVCellPhoto.userDescription layoutIfNeeded];

            [KVCellPhoto performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
            [KVCellPhoto.contentView layoutIfNeeded];
            return KVCellPhoto;
        } break;
        case EMBED_MUL_VIDEO: {
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            KVembedVideoMultipleTableViewCell
            * KVCellVideo = [tableView dequeueReusableCellWithIdentifier:@"Video Multiple" forIndexPath:indexPath];
            KVCellVideo.embededDetails = _postDict;
            [KVCellVideo setLikeDelegate:self];
            [KVCellVideo performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
            [KVCellVideo.contentView layoutIfNeeded];
            NSLog(@"card type EMBED_MUL_VIDEO");
            return KVCellVideo;
        } break;
        case EMBEDTWEET:
        case EMBED_MUL_TWEET: {
            NSLog(@"card type EMBED_MUL_TWEET");
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            KVembedTweetMultiple* KVCellTweet = [tableView dequeueReusableCellWithIdentifier:@"Tweet Multiple" forIndexPath:indexPath];
            [KVCellTweet setLikeDelegate:self];
            KVCellTweet.embededDetails = _postDict;
            KVCellTweet.embedlist = embedlist;
            [KVCellTweet.userDescription setText:discription];
            KVCellTweet.userDescriptionHeight.constant = [CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCellTweet laodUserDescription:attr];
            [KVCellTweet.userDescription updateConstraints];
            [KVCellTweet.userDescription layoutIfNeeded];

            [KVCellTweet loadTweets];

            [KVCellTweet performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:TRUE];
            [KVCellTweet.contentView updateConstraints];
            [KVCellTweet.contentView layoutIfNeeded];
            [KVCellTweet layoutIfNeeded];
            [KVCellTweet updateConstraints];
            return KVCellTweet;

        } break;
        case EMBED_MUL_AUDIO: {
            NSLog(@"card type EMBED_MUL_AUDIO");
            [_postDict setObject:indexPath forKey:KEY_INDEXPATH];
            KVembedMultiAudio* KVCellAudio = (KVembedMultiAudio*)[tableView dequeueReusableCellWithIdentifier:@"EmbedMultiAudio" forIndexPath:indexPath];
            KVCellAudio.embededDetails = _postDict;
            [KVCellAudio setLikeDelegate:self];
            KVCellAudio.userDescription.preferredMaxLayoutWidth = _timeLineTableView.bounds.size.width -16;
            [KVCellAudio.userDescription setText:discription];
            NSAttributedString *attr = [CVUtilityManager UserDescription:discription];
            KVCellAudio.userDescrptionHeight.constant =[CVUtilityManager sizeForLabel:KVCell.userDescription withAttributedString:attr];
            [KVCellAudio laodUserDescription:attr];
            [KVCellAudio.userDescription updateConstraints];
            [KVCellAudio.userDescription setNeedsLayout];
            [KVCellAudio.userDescription layoutIfNeeded];
            [KVCellAudio performSelector:@selector(laodCellContents) onThread:[NSThread mainThread] withObject:nil waitUntilDone:true];
            [KVCellAudio.contentView layoutIfNeeded];
            return KVCellAudio;
        }
            break;

        default:
            break;
    }
    [KVCell updateConstraints];
    [KVCell layoutIfNeeded];
    return KVCell;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{

    return UITableViewAutomaticDimension;

}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [self.heightAtIndexPath objectForKey:indexPath];
    if(height) {
        return height.floatValue;
    } else {
        return UITableViewAutomaticDimension;
    }
}

【问题讨论】:

  • 将 web 服务调用和图像下载移动到后台线程,以便您的 tableview 平滑滚动
  • 在你的 tableView:cellForRowAtIndexPath: 方法中发生了很多事情。您应该尽快返回单元格。这篇文章会很有帮助medium.com/ios-os-x-development/…
  • @OstapHorbach 非常感谢.. 但是在哪里为我的单元格设置数据.. 因为我使用多个自定义单元格——我无法在 willdisplay 单元格方法中设置数据..任何建议

标签: ios objective-c uitableview vertical-scrolling


【解决方案1】:

您可以对自定义单元格使用子类化。由于您对每一行都有很多自定义项,因此您可以为每一行子类化您的基本单元类。

对于设置数据,您可以创建一个数据模型对象并在您的行类中创建它的一个实例。然后你可以从 cellforRowAtIndexpath 设置你的数据模型,比如

CustomRowCell *rowCell = [[CustomRowCell alloc] init];
rowCell.dataSource = [yourDictionary objectForKey:@"key"]// yourArray[indexPath.row];

还可以使用调度队列进行服务调用。

希望对你有帮助!

【讨论】:

  • 您好,感谢您的回答---我如何子类化自定义单元格...我不是已经这样做了..
  • 是的,我现在明白了。正如我所说,您必须在子类方法中移动所有自定义,例如在您的 init 方法中。
猜你喜欢
  • 2019-07-20
  • 2014-12-06
  • 2011-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多