我在IOS 8 Objective-c iPhone应用程序中使用了Parse的PFQueryTableViewController。
我的列表包含一个标签和一个UIImageView,其中标签文本和图像都是从我的Parse核心中的一行下载的。我正在使用此代码来实现此目的:
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:@"Story"];
return query;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [[self objects] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Download the header image from parse
PFFile *imageFile = [object objectForKey:@"Image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error) {
UIImage *cellImage = [UIImage imageWithData:imageData];
// Set the cellImage to the cell if it's not nil
if (cellImage == nil) {
// nil - do nothing
NSLog(@"nil");
} else {
NSLog(@"not nil");
// Set the image
UIImageView *cellImageView = (UIImageView *)[cell viewWithTag:40];
cellImageView.image = cellImage;
}
}
}];
// Configure the cell
UILabel *nameLabel = (UILabel*) [cell viewWithTag:10];
nameLabel.text = [object objectForKey:@"Title"];
nameLabel.textColor = [UIColor whiteColor];
// Make the cell transparent
cell.backgroundColor = [UIColor clearColor];
cell.backgroundView = [UIView new];
cell.selectedBackgroundView = [UIView new];
// Resize the cell
[cell sizeToFit];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Hide the tabBar and show the readButton
[self hideTabBar:self.tabBarController];
// Segue over to the viewing page
[self performSegueWithIdentifier:@"detailSegue" sender:self];
// Get the tapped cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *title = ((UILabel*) [cell viewWithTag:10]).text;
// Set selectedStory
MyManager *sharedManager = [MyManager sharedManager];
sharedManager.selectedStory = title;
// Set openedStory to YES as we opened a story
openedStory = YES;
}
此代码效果很好,但滚动有点滞后,我认为这是因为只要显示单元格,它就会下载图像。我想通过在本地创建一个图像数组创建一个简单的解决方案,并让它们只下载一次,但它必须在应用程序启动时加载1次。我需要以某种方式异步运行下载方法(或其他可行的解决方案)。
我如何实现这一目标?
(我正在使用故事板)
修改
提前致谢! 埃里克
编辑2:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (![self.shownIndexes containsObject:indexPath]) {
[self.shownIndexes addObject:indexPath];
UIView *weeeeCell = [cell contentView];
weeeeCell.layer.transform = self.initialTransform;
weeeeCell.layer.opacity = 0.8;
[UIView animateWithDuration:1.25 delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:0.5 options:0 animations:^{
weeeeCell.layer.transform = CATransform3DIdentity;
weeeeCell.layer.opacity = 1;
} completion:^(BOOL finished) {}];
}
}
和
if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) {
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
}
答案 0 :(得分:1)
你对这个问题的假设是正确的,你对解决方案的看法也是正确的。您提到的有关预加载图像的附加要求有点模糊。
在桌子出现之前必须加载它们吗?如果它们是异步加载的,那么您应该阻止用户访问该表,直到请求完成为止。你没有立即看到图像的糟糕体验,而是根本没有看到桌子的糟糕体验。
我认为更好的答案是懒得加载。解决方案的大纲是:
声明图像字典(由indexPaths索引)并确保将其初始化为空字典...
@interface MyViewController () // replace 'MyViewController' with your class
@property(strong,nonatomic) NSMutableDictionary *images;
@end
在cellForRowAtIndexPath中使用该集合......
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *simpleTableIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UIImageView *cellImageView = (UIImageView *)[cell viewWithTag:40];
UIImage *cachedImage = self.images[indexPath];
if (cachedImage) {
cellImageView.image = cachedImage;
} else {
cellImageView.image = // put a place holder image here
// load lazily, but read on. the code in the callback should assume
// nothing about the state of the table when it runs
PFFile *imageFile = [object objectForKey:@"Image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
// what if this gets run a second time before the first request finishes?
// no worries, check for that here:
if (!error && !self.images[indexPath]) {
UIImage *cellImage = [UIImage imageWithData:imageData];
self.images[indexPath] = cellImage;
// this is important: don't refer to cell in here, it may be
// scrolled away and reused by the time this closure runs
// the code we just wrote to init the cellImageView works just fine
// call that using reload
if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) {
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
}];
}
// Configure the cell
UILabel *nameLabel = (UILabel*) [cell viewWithTag:10];
nameLabel.text = [object objectForKey:@"Title"];
nameLabel.textColor = [UIColor whiteColor];
// Make the cell transparent
cell.backgroundColor = [UIColor clearColor];
cell.backgroundView = [UIView new];
cell.selectedBackgroundView = [UIView new];
// Resize the cell
[cell sizeToFit];
return cell;
}
编辑 - 现在不要为此烦恼,但是 - 如果你确实有机会在显示之前准备视图(就像这个视图控制器可能在标签栏容器中而不是默认值标签)。您可以使用表视图助手方法来预取可见行...
- (void)prepareToBeShown {
NSArray indexPaths = [self.tableView indexPathsForVisibleRows];
[self.tableView reloadRowsAtIndexPaths:indexPaths];
}
编辑2:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (![self.shownIndexes containsObject:indexPath]) {
[self.shownIndexes addObject:indexPath];
UIView *weeeeCell = [cell contentView];
weeeeCell.layer.transform = self.initialTransform;
weeeeCell.layer.opacity = 0.8;
[UIView animateWithDuration:1.25 delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:0.5 options:0 animations:^{
weeeeCell.layer.transform = CATransform3DIdentity;
weeeeCell.layer.opacity = 1;
} completion:^(BOOL finished) {}];
}
}
答案 1 :(得分:0)
您是否考虑过使用PFImageView而不是UIImageView?
所有你必须这样做设置它的文件并告诉它在后台加载。在我的tableviews中使用它们时,我从来没有任何延迟。