背景资料
目前,我正在使用以下代码为UITableViewCell中的每个UITableView设置文本:
方案A:cell.textLabel.attributedText = [news formattedSubject];但是,请考虑是否要为formattedSubject定义添加一个参数,只是一个整数参数,因此代码现在为:
方案B:cell.textLabel.attributedText = [news formattedSubject:1];每个表格视图单元格中的文本大约3-5行,并从外部来源读取并通过JSON进行解析。这是所需结果的图,这是方案A 中发生的情况:
方案A流程图:

图片A仅显示应用仍在加载JSON数据时获得的默认空UITableView。应用程序检索并解析了这些数据之后,便将数据填充到UITableView中,从而生成图像B。这是期望的(和预期的)结果。
但是,如果将参数添加到formattedSubject,则会获得以下流程图:
方案B流程图:

图像A再次显示默认的UITableView。但是,问题出在图像B中。 在图像B中,数据已被解析,但是尚未通过formattedSubject正确格式化,因此导致单个,水平狭窄且较长的未格式化文本行。 在几分之一秒后,该应用程序看起来像图像C,最终结果显示了经过解析的格式化数据。
我的问题:
我所做的唯一更改是在formattedSubject中添加了一个参数。 也就是说,我将-(NSAttributedString*)formattedSubject {更改为-(NSAttributedString*)formattedSubject:(int)state {没关系,formattedSubject中没有任何东西实际上使用了state整数,我仍然从场景B中得到结果。
此更改似乎使代码运行速度更慢。它在解析数据与格式化并在UITableView中显示数据之间创建了一个延迟。我很好奇这是为什么,以及如何解决/避免这个问题。
除了美学上的问题外,场景B中的情况还会在用户到达UITableView的末尾时干扰我自动加载新数据。由于文本水平缩小,因此最后一行数据在首次加载时即刻显示在UITableView中,即,从而导致在应用程序启动时两次检索到数据。
我距离编码专家还很遥远,因此,对我来说,在NSAttributedString中简单地添加参数会产生上述延迟是绝对没有道理的。如果有人可以,我将不胜感激:

  • 解释为什么会发生,以及
  • 提供解决此问题的解决方案。

  • 非常感谢您阅读本文,我们欢迎任何评论/帮助。
    编辑1:@ Vijay-Apple-Dev.blogspot.com,@txulu
    这是我的 formattedSubject 代码:
    -(NSAttributedString*)formattedSubject:(int)state {
        if(formattedSubject!=nil) return formattedSubject;
        NSDictionary *boldStyle = [[NSDictionary alloc] init];
        if(state==1) {
            boldStyle = @{NSFontAttributeName:[UIFont fontWithName:@"Helvetica-Bold" size:16.0],NSForegroundColorAttributeName:[UIColor colorWithRed:0.067 green:0.129 blue:0.216 alpha:1.0]};
        }
        else {
            boldStyle = @{NSFontAttributeName:[UIFont fontWithName:@"Helvetica-Bold" size:16.0],NSForegroundColorAttributeName:[UIColor whiteColor]};
        }
        NSDictionary* normalStyle = @{NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:14.0]};
        NSMutableAttributedString* articleAbstract = [[NSMutableAttributedString alloc] initWithString:subject];
        [articleAbstract setAttributes:boldStyle range:NSMakeRange(0, subject.length)];
        [articleAbstract appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]];
        int startIndex = [articleAbstract length];
        NSTimeInterval _interval=[datestamp doubleValue];
        NSDate *date = [NSDate dateWithTimeIntervalSince1970:_interval];
        NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
        [_formatter setDateFormat:@"MM/dd/yy"];
        NSString* description = [NSString stringWithFormat:@"By %@ on %@",author,[_formatter stringFromDate:date]];
        [articleAbstract appendAttributedString:[[NSAttributedString alloc] initWithString: description]];
        [articleAbstract setAttributes:normalStyle range:NSMakeRange(startIndex, articleAbstract.length - startIndex)];
        formattedSubject = articleAbstract;
        return formattedSubject;
    }
    
    请注意,正如我之前说的,即使我实际上没有使用state参数,我仍然会得到相同的结果。
    这是我的 cellForRowAtIndexPath 代码:
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    
        News *news = newsArray[indexPath.row];
    
        NSIndexPath *selectedIndexPath = [tableView indexPathForSelectedRow];
        if([selectedIndexPath isEqual:indexPath]) {
            cell.textLabel.attributedText = [news formattedSubject:1];
        }
        else {
            cell.textLabel.attributedText = [news formattedSubject:0];
        }
    
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
        UIView *selectedBackgroundViewForCell = [UIView new];
        [selectedBackgroundViewForCell setBackgroundColor:[UIColor colorWithRed:0.169 green:0.322 blue:0.525 alpha:1.0]];
        cell.selectedBackgroundView = selectedBackgroundViewForCell;
        cell.textLabel.highlightedTextColor = [UIColor whiteColor];
        if (indexPath.row == [newsArray count] - 1) {
            [self parseJSON];
        }
        return cell;
    }
    
    请让我知道是否可以发布其他任何有帮助的信息。
    编辑2:
    我不确定是否存在性能问题。经过进一步测试,我倾向于认为,在方案A中,该应用程序先加载并格式化单元格数据,然后再将其显示在上,而在方案B中,该应用程序加载数据,并以UITableViewCell进行显示,然后先将的数据显示为格式它,这产生了我上面详细介绍的问题。
    有人在我的parseJSON方法中调出了代码,因此我将其发布在这里以供参考。如您所见,我确实实现了多线程,以防止数据加载滞后于应用程序。
    -(void)parseJSON
    {
        loading.alpha = 1;
        loading.image = [UIImage imageNamed:@"loading.png"];
        activityIndicator.alpha = 1;
        timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(checkLoading) userInfo:nil repeats:YES];
    
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
        dispatch_async(queue, ^{
            parseNumber = parseNumber + 1;
            int offset = parseNumber*20-1;
            NSString *URLString = [NSString stringWithFormat:@"http://feedurl.com/feed.php?offset=%d",offset];
            NSURL *url=[NSURL URLWithString:URLString];
            NSData *data=[NSData dataWithContentsOfURL:url];
            NSError* error;
            if(data!=nil) {
                json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &error];
                for(NSDictionary *newsInfo in json) {
                    News *newsList = [[News alloc] init];
                    newsList.thread = newsInfo[@"thread"];
                    newsList.author = newsInfo[@"author"];
                    newsList.subject = newsInfo[@"subject"];
                    newsList.body= newsInfo[@"body"];
                    newsList.datestamp = newsInfo[@"datestamp"];
                    [jsonTemp addObject:newsList];
                }
                newsArray = jsonTemp;
            }
            dispatch_sync(dispatch_get_main_queue(), ^{
                if(data!=nil) {
                    [newsTable reloadData];
                }
                else {
                    activityIndicator.alpha = 0;
                    loading.image = [UIImage imageNamed:@"error.png"];
                    [self startTimer];
                }
            });
        });
    }
    

    最佳答案

    编辑:

    好的,调用[news formattedSubject]而不是[news formattedSubject:1]有所不同。第一个就像做news.formattedSubject一样,这就是访问快速返回ivar的formattedSubject属性。第二个调用较复杂的formattedSubject:方法,该方法执行您发布的代码的速度较慢。

    原始:

    您的代码看起来不错,除了一些小细节,例如:

    NSDictionary *boldStyle = [[NSDictionary alloc] init];
    

    不需要,因为您是在之后分配的:
    boldStyle = @{NSFontAttributeName ...}
    

    另外,我猜可能导致您的问题的原因是:
    if (indexPath.row == [newsArray count] - 1) {
        [self parseJSON];
    }
    

    在cellForRowAtIndexPath:内部调用此函数可能会导致严重的性能问题。如果此方法做了很多工作并且没有在后台执行,则可能导致您提到的延迟。根据经验,永远不要在主线程中进行网络/数据处理(cellForRowAtIndexPath将始终由系统在该线程中调用)。

    关于ios - 传递参数会使代码运行“更慢”吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22320930/

    10-11 20:07