首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何提高加载UITableViewController的速度

如何提高加载UITableViewController的速度
EN

Stack Overflow用户
提问于 2016-05-20 00:23:24
回答 2查看 125关注 0票数 0

我有一个从后端填充的UITableViewController。该单元格是一个自定义单元格,它具有:

  • 1 UIImageView (与clipBounds和圆角环绕)将在cellForRowAtIndexPath中异步加载。
  • 3 UIImageViews预加载(45 px30 one和700个字节,每个字节)
  • 4 UILabels

这是加载表的代码:

代码语言:javascript
复制
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];

[_activity startAnimating];
NSString *urlString = @"http://blablabla.com/getmydata";
NSLog(@"Loading URL=%@", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                       cachePolicy:BACKEND_CACHE_POLICY
                                                   timeoutInterval:BACKEND_TIMEOUT_ASINC];

[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *receivedData, NSError *error) {
                           NSLog(@"Received data: %@", [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding]);
                           NSError *jsonParsingError = nil;
                           NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:receivedData
                                                                                    options:0
                                                                                      error:&jsonParsingError];

                           dispatch_async(dispatch_get_main_queue(), ^{
                               [_activity stopAnimating];
                               NSLog(@"Stop animating");
                               myData = [receivedData objectForKey:@"data"];
                               [mytable reloadData];
                           });

                       }];
}

代码语言:javascript
复制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Just before dequeueReusableCellWithIdentifier for row %d", indexPath.row);
CustomViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSLog(@"Just after dequeueReusableCellWithIdentifier for row %d", indexPath.row);
NSDictionary *data = [_items objectAtIndex:indexPath.row];
NSString *photo = [data objectForKey:@"photo_url"];
if([photo isKindOfClass:[NSNull class]])
    photo = @"";
NSString *title = [data objectForKey:@"title"];
if([title isKindOfClass:[NSNull class]])
    title = @"";
NSString *subtitle = [data objectForKey:@"subtitle"];
if([subtitle isKindOfClass:[NSNull class]])
    subtitle = @"";
NSString *author = [data objectForKey:@"author"];
if([author isKindOfClass:[NSNull class]])
    author = @"";
NSString *createdAt = [data objectForKey:@"created_at"];
if([createdAt isKindOfClass:[NSNull class]])
    createdAt = @"";
MyImageDownloader *downloadingImage = [_downloadingImages objectForKey:indexPath];
if (downloadingImage == nil)
{
    if ((photo != nil) && (![photo isEqualToString:@""]))
    {
        [self startImageDownload:photo forIndexPath:indexPath];
    }
    [cell.photoIV setImage:[UIImage imageNamed:@"noimage"]];
}
else
{
    [cell.photoIV setImage:downloadingImage.image];
}
[cell.titleLb setText:title];
[cell.subtitleLb setText:subtitle];
[cell.authorLb setText:author];
[cell.createdAtLb setText:createdAt];
return cell;
}

如果我运行这个,这就是输出:

代码语言:javascript
复制
2016-05-20 02:14:22.571 MyApp[7913:2037477] Loading URL=http://blablabla.com/getmydata
2016-05-20 02:14:23.233 MyApp[7913:2037477] Received data: data for 3 items.
2016-05-20 02:14:23.240 MyApp[7913:2037477] Stop animating
2016-05-20 02:14:23.242 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:28.784 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:28.791 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:28.818 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:28.821 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 2
2016-05-20 02:14:28.842 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 2
2016-05-20 02:14:28.858 MyApp[7913:2037477] Unable to simultaneously satisfy constraints.(some problems with the labels, but in the Interface Builder there are no warnings)
2016-05-20 02:14:28.873 MyApp[7913:2037477] Unable to simultaneously satisfy constraints.(some problems with the labels, but in the Interface Builder there are no warnings)
2016-05-20 02:14:28.887 MyApp[7913:2037477] Unable to simultaneously satisfy constraints.(some problems with the labels, but in the Interface Builder there are no warnings)
2016-05-20 02:14:29.645 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:29.649 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:29.650 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:29.651 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:29.652 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 2
2016-05-20 02:14:29.653 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 2
2016-05-20 02:14:29.656 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:29.657 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 0
2016-05-20 02:14:29.658 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:29.659 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 1
2016-05-20 02:14:29.661 MyApp[7913:2037477] Just before dequeueReusableCellWithIdentifier for row 2
2016-05-20 02:14:29.662 MyApp[7913:2037477] Just after dequeueReusableCellWithIdentifier for row 2

如你所见,第一个dequeueReusableCellWithIdentifier需要5秒!!

我试图在dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0中封装NSURLConnection sendAsynchronousRequest ),但是结果是一样的。

为什么要花这么长时间?我遗漏了什么?

编辑1:

  • 关于cellForRow,我刚刚编辑了上面的方法,所以它包含了完整的代码。
  • 关于JSON解析,我将考虑这些建议,但正如你们中的一些人所指出的,问题不是这个过程,而是单元格的第一次加载。
  • 为了加载远程图像异步,我使用了一个由我自己创建的类,但正如我所看到的,它非常类似于SDWebImage。
  • 我尝试在viewDidLoad中进行第一次加载,但没有成功,该表仍然需要5秒才能加载。
  • 关于cellId,我在viewDidLoad中这样做: UINib *nib = UINib nibWithNibName:@"CustomViewCell“bundle:nil; mytable寄存器nib:nib nib:@“Cell”; mytable setRowHeight: UITableViewAutomaticDimension;
  • 最重要的是,受安德鲁·罗曼诺夫( Andrew )的启发,他回答说:“你能用很长的时间把弦移开,让所有人都知道吗?”我决定从单元格XIB文件中完全删除4 UILabels和表加载超快(两个预加载映像和后端异步映像),所以问题在于UILabels。
  • 知道了这一点,我尝试删除其中的一些,但结果是相同的,只有一个UILabel (不管哪个),表仍然需要5秒来加载第一个单元格。
  • 我尝试在4 UIlabels中添加一个宽度和高度约束,以防计算单元格尺寸的问题,但该表仍然需要5秒来加载第一个单元格。如果你认为这可能是一个问题,奥托莱外的细胞,我将尝试张贴的限制。

因此,最后,问题在于UILabels在单元格XIB中,我已经实现了大量的自定义单元格,它们的布局更加复杂,没有任何问题,所以这次我肯定遗漏了一些东西。

编辑2:

按照Andrew的建议,我已经在dequeueReusableCellWithIdentifier中设置了一个断点,我跳过去并暂停调试器。由于细节太低,我不太明白:

代码语言:javascript
复制
UIKit`-[UITableView dequeueReusableCellWithIdentifier:forIndexPath:]:
0x29ee6d84 <+0>:   push   {r4, r5, r6, r7, lr}
0x29ee6d86 <+2>:   add    r7, sp, #0xc
0x29ee6d88 <+4>:   push.w {r8, r10, r11}
0x29ee6d8c <+8>:   sub    sp, #0x10
0x29ee6d8e <+10>:  mov    r5, r0
0x29ee6d90 <+12>:  movw   r0, #0xbc52
0x29ee6d94 <+16>:  movt   r0, #0xbb8
0x29ee6d98 <+20>:  mov    r10, r1
0x29ee6d9a <+22>:  add    r0, pc
0x29ee6d9c <+24>:  mov    r4, r2
0x29ee6d9e <+26>:  mov    r8, r3
0x29ee6da0 <+28>:  ldr    r1, [r0]
0x29ee6da2 <+30>:  mov    r0, r5
0x29ee6da4 <+32>:  blx    0x2a4a2240                ; symbol stub for: CFDictionaryRemoveAllValues$shim
->  0x29ee6da8 <+36>:  mov    r6, r0
0x29ee6daa <+38>:  cbnz   r6, 0x29ee6e1c            ; <+152>
0x29ee6dac <+40>:  movw   r0, #0xb99c
0x29ee6db0 <+44>:  movt   r0, #0xbb8
0x29ee6db4 <+48>:  movw   r2, #0x1c36
0x29ee6db8 <+52>:  movt   r2, #0xbba

该指令"0x29ee6da8 <+36>:mov r6,r0“在第一次执行时花费了5秒,并且在其他执行过程中非常快。

除此之外,哪个仪器可以最好地调试这个问题呢?

修好了!!

按照Andrew的建议,我复制和粘贴了堆栈跟踪,并发现时间很长是由于加载了自定义字体(这4个标签使用了在Info.plist中正确定义的自定义字体)。我所做的是为systemFont设置UILabels,并在willDisplayCell方法中设置自定义字体。这样桌子装得很快。

不好意思,我怎么才能回答这个问题呢?我应该自己回答并检查一下吗?非常感谢安德鲁!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-22 17:14:32

这个问题是由细胞内的UILabels引起的。他们使用了自定义字体,我在单元格XIB文件中设置了这种字体,所以当表第一次加载单元格时,它加载自定义字体,这需要很长时间。

我为解决这个问题所做的是:

  1. 在XIB文件中,将UILabels的字体设置为系统字体,因此当它第一次加载单元格时,自定义字体没有加载时间。
  2. 然后,在UILabels Delegate方法中设置UITableView自定义字体:
代码语言:javascript
复制
- (void) tableView:(UITableView \*)tableView willDisplayCell:(UITableViewCell \*)cell forRowAtIndexPath:(NSIndexPath \*)indexPath

这样,加载第一个单元格的时间非常短。

票数 0
EN

Stack Overflow用户

发布于 2016-05-20 04:20:34

您是在代码中还是在xib文件中实现单元格的UI?如果在xib中可能是您没有在xib中配置cellId?

我还看到,只有第一个单元格被创建了很长时间,我认为在第一次初始化之后会缓存一些内容。

如果在排序板文件中配置单元格,请尝试将单元格的UI移动到Xib文件,并使用方法 of UITableView为单元格注册一个nib:

代码语言:javascript
复制
- (void)registerNib:(UINib *)nib  forCellReuseIdentifier:(NSString *)identifier

此外,您还可以尝试在此屏幕之前的某个地方(例如,在加载数据时)从nib中启动单元,然后该系统可以将数据保存在现金中以避免从磁盘读取文件。

此外,您还可以在使用方法加载数据时,将图像加载到后台缓存。

代码语言:javascript
复制
+ (UIImage *)imageNamed:(NSString *)name
               inBundle:(NSBundle *)bundle
compatibleWithTraitCollection:(UITraitCollection *)traitCollection

代码语言:javascript
复制
+ (UIImage *)imageNamed:(NSString *)name

从文件中:

如果缓存中还没有匹配的映像对象,则此方法将定位并从磁盘或可用资产目录加载图像数据,然后返回结果对象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37336105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档