我有一个从后端填充的UITableViewController。 该单元格是一个自定义单元格,具有:
这是我加载表格的代码:
- (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];
});
}];
}
和
- (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;
}
如果我运行它,这是输出:
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 registerNib:nib forCellReuseIdentifier:@“Cell”];
[mytable setRowHeight:UITableViewAutomaticDimension];
主要的事情,灵感来自安德鲁·罗曼诺夫(Andrew Romanov)的回答“你能不能长时间地移出琴弦来展示它?”我已经决定从单元格XIB文件中完全删除4个UILabel和表加载超高速(两个预加载的图像和后端的异步图像),所以问题出在UILabels上。
知道这一点我试图删除其中的一些,但结果是一样的,只有一个UILabel(无关紧要哪一个)表仍然需要5秒才能加载第一个单元格。 / p>
我试图在4个UI标签上添加宽度和高度约束,以防万一这是计算单元格尺寸的问题,但表格仍需要5秒钟来加载第一个单元格。如果您认为该单元格的Autolayout可能存在问题,我会尝试发布约束。
所以,最后,问题在于单元格XIB中的UILabel,我已经实现了多次自定义单元格,布局更复杂,没有任何问题所以这次我确定我遗漏了一些东西。
编辑2:
根据Andrew Romanov的建议,我在dequeueReusableCellWithIdentifier中设置了一个断点,我跳过并暂停调试器。如此低级别的细节,我不太了解:
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&lt; + 36&gt;:mov r6,r0”第一次需要5秒,并且其余的执行速度超高。
除此之外,什么仪器可以最好地调试这个问题?
固定!!
根据Andrew Romanov的建议,我复制并粘贴了堆栈跟踪,发现很长时间是由于加载了自定义字体(4个标签使用了Info.plist中正确定义的自定义字体)。 我所做的是为UILabels设置systemFont并在willDisplayCell方法中设置自定义字体。这样表的加载速度非常快。
对于offtopic我很抱歉,我怎么能将这个问题设置为已回答?我该回答并检查一下吗? 非常感谢Andrew!
答案 0 :(得分:0)
您是在代码中还是在xib文件中实现Cell的UI?如果在xib中你可能没有在xib中配置cellId? 另外我看到只有第一个单元格被创建了很长时间,我认为在第一次初始化之后会缓存一些内容 如果在soryboard文件中配置单元格,请尝试将Cell的UI移动到Xib文件,并使用UITableView的method为该单元格注册一个nib:
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
此外,您可以在此屏幕之前的某个地方(例如,在加载数据时)从nib尝试initiate the cell,之后系统可以将数据保存为现金以避免从磁盘读取文件。
此外,您可以在使用method加载数据时将图像加载到后台缓存中:
+ (UIImage *)imageNamed:(NSString *)name
inBundle:(NSBundle *)bundle
compatibleWithTraitCollection:(UITraitCollection *)traitCollection
或
+ (UIImage *)imageNamed:(NSString *)name
来自文档:
如果匹配的图像对象尚未在缓存中,则此方法 从磁盘或可用资产中查找并加载图像数据 目录,然后返回结果对象。
答案 1 :(得分:0)
问题是由细胞内的UILabels引起的。他们使用自定义字体,我在单元格XIB文件中设置,所以第一次表格加载单元格时,它会加载自定义字体,这需要花费很多时间。
我为解决这个问题所采取的措施是:
在XIB文件中,将UILabels的字体设置为系统字体,因此第一次加载单元格时,自定义字体没有加载时间。
然后,在UITableView Delegate方法中设置UILabels自定义字体:
这样加载第一个单元格的时间非常短。