传递参数会使代码运行“更慢”吗?

时间:2014-03-11 09:05:01

标签: ios objective-c uitableview nsattributedstring

背景资料

目前,我正在使用以下代码为UITableViewCell中的每个UITableView设置文字:

情景A:

cell.textLabel.attributedText = [news formattedSubject];

但是,考虑我是否要为formattedSubject定义添加一个参数,只需要一个整数参数,所以代码现在是:

情景B:

cell.textLabel.attributedText = [news formattedSubject:1];

每个表格视图单元格中的文本长度大约为3-5行,并从外部源读取并通过JSON解析。这是期望结果的图表,即场景A 中发生的结果:

场景A流程图:

enter image description here

图像A只显示应用程序仍在加载JSON数据时获得的默认空UITableView。在应用程序检索并解析此数据后,它会将数据填充到UITableView中,从而生成图像B. 这是期望的(和预期的)结果。

但是,如果我向formattedSubject添加一个参数,我会得到下面的流程图:

场景B流程图:

enter image description here

图片A再次显示默认UITableView。但是,这就是图像B中发生的问题。 在图片B中,数据已被解析,但尚未由formattedSubject正确格式化,从而导致单行,水平窄且冗长的无格式文本行。应用程序看起来像Image C,最终结果是在解析后显示格式化数据。

我的问题:

我做的唯一更改是向formattedSubject添加了一个参数。 也就是说,我将-(NSAttributedString*)formattedSubject {更改为-(NSAttributedString*)formattedSubject:(int)state { formattedSubject中没有任何内容实际使用并不重要state整数,我仍然从方案B得到结果。

这种变化似乎使代码运行得更慢。它会在解析数据和在UITableView中格式化和显示数据之间产生延迟。我很好奇为什么会这样,以及我如何解决/规避这个问题。

除了是一个美学问题,场景B 中发生的事情也会干扰我在用户到达UITableView末尾时自动加载新数据。由于水平缩小的文本行,最后一行数据会在首次加载时暂时显示在UITableView中,因此会导致数据在应用启动时检索两次。 / p>

我与编码方面的专家无关,因此对我来说如何简单地向我的NSAttributedString添加参数可能会产生上述延迟是完全没有意义的。如果有人可以,我会非常感激:

  1. 解释为什么这种情况正在发生,
  2. 提供解决方案以解决此问题。
  3. 非常感谢您阅读本文,欢迎任何评论/帮助。

    编辑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中,应用程序加载数据,将其显示在{{ 1}},然后然后格式化它,这会产生我上面详述的问题。

    有些人在我的UITableViewCell方法中提出了代码,因此我将其发布在此处以供参考。正如您所看到的,我确实实现了多线程,以防止数据加载滞后于应用程序。

    parseJSON

2 个答案:

答案 0 :(得分:1)

修改

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

<强>原始

您的代码似乎很好,除了一些小细节,如:

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

没有必要,因为你刚刚分配:

boldStyle = @{NSFontAttributeName ...}

此外,我猜可能导致您的问题是:

if (indexPath.row == [newsArray count] - 1) {
    [self parseJSON];
}

在你的cellForRowAtIndexPath中调用它可能是一个严重的性能问题。如果这种方法做了很多工作但没有在后台执行,那么可能会导致你提到的延迟。根据经验,您绝不应该在主线程中进行网络/数据处理(系统将始终在该线程中调用cellForRowAtIndexPath)。

答案 1 :(得分:0)

你说如下

&#34;每个表格视图单元格中的文本长度大约为3-5行,从外部源读取并通过JSON 解析。这是所需结果的图表,即情景A中发生的情况:&#34;

我假设您正在阅读

中的数据

1.本地核心数据库

2.Web服务器的数据库。

对于案例1,您应该使用NSFetchedResultsController,跟进本教程

https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html

http://www.raywenderlich.com/999/core-data-tutorial-for-ios-how-to-use-nsfetchedresultscontroller

对于案例2,您应该在后台线程中执行,并在tableview中通过主线程更新它,如果可用,请按照本教程进行操作

How to load JSON asynchronously (iOS)