为什么我的UITableViewCell图像只在我离开然后返回控制器时加载,而不是在viewDidLoad期间加载



我的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

最新更新