我的UITableViewCell图像有一点问题。我直接从 parse.com 加载数据。返回 PFObject 的对象数组存储在名为"people"的 NSMutable 数组中。
这是我在表中显示数据的方式:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [[self tableView] dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
Person *current;
if (tableView == [[self searchDisplayController] searchResultsTableView]) {
current = [searchResults objectAtIndex:indexPath.row];
} else {
current = [people objectAtIndex:[indexPath row]];
}
[[cell textLabel] setText: [current valueForKey:@"name"]];
PFFile *userImageFile = [current valueForKey:@"image"];
[userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
UIImage *image = [UIImage imageWithData:imageData];
[[cell imageView] setImage: image];
}];
// [[cell imageView] setImage: [current image]];
[[cell detailTextLabel] setText: [current valueForKey:@"notes"]];
return cell;
}
问题是当我加载应用程序并且这个视图是我的主要加载时,它不会加载任何图像。但是,当我在屏幕上弹出下一个控制器之前点击一行时,我会看到该行加载的图像,然后当我点击后退按钮并再次返回主视图时,tableViews 图像的其余部分加载。
这与图像不是缩略图版本有关吗?
我尝试将代码包装在dispatch_async(dispatch_get_main_queue(), ^ { )};
中,但没有运气。有人可以帮助我解决这个问题吗?
亲切问候
更新以显示我调用重新加载数据的位置:
-(void)viewDidAppear:(BOOL)animated {
dispatch_async(dispatch_get_main_queue(), ^{
[[self tableView] reloadData];
});
}
- (void)viewDidLoad
{
[super viewDidLoad];
people = [[NSMutableArray alloc] init];
PFQuery *query = [PFQuery queryWithClassName:@"People"];
[query whereKey:@"active" equalTo:@1];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
people = objects.mutableCopy;
dispatch_async(dispatch_get_main_queue(), ^ {
[[self tableView] reloadData];
});
我认为您在viewDidLoad中的加载没有任何问题。
我怀疑 UIImageView 的帧实际上为零,因为在加载实际图像时您没有占位符图像。在下次再次调用 layoutSubviews 之前,不会再次重绘单元格,即使已加载获取的图像也是如此。因此,要么设置占位符图像,要么调用:
[cell setNeedsLayout];
一旦您的图像完全加载。
另一种选择是使用PFImageView,这是UIImageView的一个子类,它会为您处理所有事情。
PFFile *userImageFile = [current valueForKey:@"image"];
[cell imageView].image = [UIImage imageNamed:@"placeholder.jpg"]; // placeholder image
[cell imageView].file = userImageFile;
[[cell imageView] loadInBackground];
将数据直接从 parse.com 加载到我的 tableView 中,而是先将其加载到一个对象中。因此,每个对象都不再是 PFObject,现在是 Person 对象,我将它们存储在一个可变数组中,我在 tableView 中访问了该数组。
试试看:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear]; //this is necessary for most time
//viewDidAppear be called in main thread, so just call reloadData directly
[self.tableView reloadData];
}
正如苹果文档中提到的关于- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath
:
在调用此方法之前,必须使用 registerNib:forCellReuseIdentifier:
或 registerClass:forCellReuseIdentifier:
方法注册类或 nib 文件。
如果为指定的标识符注册了一个类,并且必须创建一个新单元,则此方法通过调用其 initWithStyle:reuseIdentifier:
方法来初始化该单元。
对于基于 nib 的单元格,此方法从提供的 nib 文件加载单元格对象。如果现有单元格可供重用,则此方法将改为调用该单元格的 prepareForReuse
方法。
那么,在调用该方法之前,您是否忘记使用 registerNib:forCellReuseIdentifier:
或 registerClass:forCellReuseIdentifier:
方法cellForRowAtIndexPath
?
这是关于这个问题的讨论。
How I am doing this
In my UIViewController.m
@property (nonatomic, strong) NSMutableDictionary *imageDownloadsInProgress;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
SRKProduct *productRecord = [stockArray objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (!productRecord.image || [productRecord.image isEqualToData:NULL] || productRecord.image.length == 0) {
if (_itemTableView.dragging == NO && _itemTableView.decelerating == NO)
{
[self startIconDownload:productRecord forIndexPath:indexPath];
}
cell.imageView.image = [[UIImage imageNamed:@"Placeholder.png"] makeThumbnailOfSize:CGSizeMake(50,50)];//This is just a placeholder and will be removed when original image is downloaded.
}
return cell;
}
#pragma mark -
- (void)startIconDownload:(SRKProduct *)srkproduct forIndexPath:(NSIndexPath *)indexPath
{
SRKIconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[SRKIconDownloader alloc] init];
iconDownloader.srkproduct = srkproduct;
[iconDownloader setCompletionHandler:^{
UITableViewCell *cell = [_itemTableView cellForRowAtIndexPath:indexPath];
// Display the newly loaded image
cell.imageView.image = [UIImage imageWithData:srkproduct.image];
NSLog(@"Image %d",[productAdapter updateproductImage:srkproduct]);
// Remove the IconDownloader from the in progress list.
// This will result in it being deallocated.
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
Then in SRKIconDownloader.h
@interface SRKIconDownloader : NSObject
@property (nonatomic, strong) SRKProduct *srkproduct;
@property (nonatomic, copy) void (^completionHandler)(void);
And in SRKIconDownloader.m
@implementation SRKIconDownloader
#pragma mark
- (void)startDownload
{
PFQuery *queryCouple = [PFQuery queryWithClassName:@"Product"];
[queryCouple whereKey:@"Name" equalTo:_srkproduct.productName];
[queryCouple findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
if ([objects count] > 0) {
for (PFObject *object in objects) {
PFFile *image = (PFFile *)[object objectForKey:@"Image"];
[image getDataInBackgroundWithBlock:^(NSData *data, NSError *error){
_srkproduct.image = data;
// call our delegate and tell it that our icon is ready for display
if (self.completionHandler)
self.completionHandler();
}];
break;
}
}
else{
}
}
}];
}
@end