RootViewController - tableView:cellForRowAtIndexPath - 从 assetLibrary 加载图像

发布于 2024-12-07 09:40:50 字数 2491 浏览 2 评论 0原文

StackOverflow 的朋友和同事程序员,

我的 RootViewController(视图上的 FlowerTableView)应该显示带有标题、副标题和图像缩略图(从相机胶卷加载)的单元格。我想这是一个非常基本的表格。

所有内容都存储在“核心数据”中,但图像存储为相机胶卷的图像路径。示例:flower.imagePath = assets-library://asset/asset.JPG?id=1000000002&ext

使用底部的代码,一切都应该顺利运行,但事实并非如此。启动应用程序时,会显示标题和副标题,但不会显示图像。当我按下一个单元格(显示详细视图)并再次弹出到主视图时,会显示该特定单元格的图像。

当我按下“显示全部”(工具栏上的一个按钮,该按钮执行以下代码

NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest];
[fetchRequest setPredicate:nil];

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}
[self.flowerTableView reloadData];

并重新加载表格)时,现在会显示所有美丽的花朵。

为什么第一次没有放花呢?这是缓存问题吗?

调试此代码时,字符串:“此调试字符串在完成此功能后被记录”是在启动应用程序加载表格后记录的,而不是在按“显示全部”后记录的 这意味着所有图像均已从相机胶卷成功加载,但在显示单元格后附加到单元格,因此未显示。

当按“显示全部”时,会按预期打印同一行

希望有人能告诉我这里发生了什么,甚至更好的是,要在我的代码中更改哪些内容才能使这项工作正常进行。我现在被困住了...

感谢您帮助我! 埃德温

::代码:::

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath
{

    Flower *flower = [fetchedResultsController_ objectAtIndexPath:indexPath];

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...

    // Display the image if one is defined
    if (flower.imagePath && ![flower.imagePath isEqualToString:@""])
    {
        // Should hold image after executing the resultBlock
       __block UIImage *image = nil;

        ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *asset)
        {
            NSLog(@"This debug string was logged after this function was done");
            image = [[UIImage imageWithCGImage:[asset thumbnail]] retain];
        };

        ALAssetsLibraryAccessFailureBlock failureBlock  = ^(NSError *error)
        {
            NSLog(@"Unresolved error: %@, %@", error, [error localizedDescription]);
        };

        [assetsLibrary_ assetForURL:[NSURL URLWithString:flower.imagePath] 
                        resultBlock:resultBlock
                       failureBlock:failureBlock];

        [cell.imageView setImage:image];
    }

    return cell;
}

StackOverflow friends and colleague programmers,

My RootViewController (a flowerTableView on a view) should display cell's with title, subtitle and an image thumbnail (loaded from the camera roll). A very basic table I guess.

All content is stored in 'Core Data' but the images are stored as imagePaths to the camera roll. Example: flower.imagePath = assets-library://asset/asset.JPG?id=1000000002&ext

Using the code at the bottom everything should run smoothly but it doesn't . When starting the App the title's and subtitle's are shown, but the images are not. When I press a cell, which display's the detail view, and pop back again to the main view the image for this specific cell is shown.

When I press 'Show All', a button on a toolbar which executes the following code

NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest];
[fetchRequest setPredicate:nil];

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}
[self.flowerTableView reloadData];

and reloads the table, all the beautiful flowers are now shown.

Why didn't the flowers be displayed the first time? Is this a caching problem?

When debugging this code the string: 'This debug string was logged after this function was done' was logged after loading the table on starting the app, not after pressing 'Show All'
This means that all images are loaded from the camera roll successfully but attached to the cell after the cell was displayed and therefore not shown.

The same line is printed as intended when pressing 'Show All'

Hope someone can tell me what's going on here and even better, what to change in my code to make this work. I'm stuck at the moment...

Thank for helping me out!
Edwin

:::THE CODE:::

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath
{

    Flower *flower = [fetchedResultsController_ objectAtIndexPath:indexPath];

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...

    // Display the image if one is defined
    if (flower.imagePath && ![flower.imagePath isEqualToString:@""])
    {
        // Should hold image after executing the resultBlock
       __block UIImage *image = nil;

        ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *asset)
        {
            NSLog(@"This debug string was logged after this function was done");
            image = [[UIImage imageWithCGImage:[asset thumbnail]] retain];
        };

        ALAssetsLibraryAccessFailureBlock failureBlock  = ^(NSError *error)
        {
            NSLog(@"Unresolved error: %@, %@", error, [error localizedDescription]);
        };

        [assetsLibrary_ assetForURL:[NSURL URLWithString:flower.imagePath] 
                        resultBlock:resultBlock
                       failureBlock:failureBlock];

        [cell.imageView setImage:image];
    }

    return cell;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沧桑㈠ 2024-12-14 09:40:50

-[ALAssetsLibrary assetForURL:resultBlock:failureBlock] 异步运行。这意味着调用会立即在 tableView:cellForRowAtIndexPath: 方法中返回。在实际加载资源之前,该单元格会显示在表视图中。

您需要做的是设置结果块中单元格的图像。像这样的事情:

if (flower.imagePath && ![flower.imagePath isEqualToString:@""])
{
    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *asset)
    {
        NSLog(@"This debug string was logged after this function was done");
        [cell.imageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];

        //this line is needed to display the image when it is loaded asynchronously, otherwise image will not be shown as stated in comments
        [cell setNeedsLayout]; 

    };

    ALAssetsLibraryAccessFailureBlock failureBlock  = ^(NSError *error)
    {
        NSLog(@"Unresolved error: %@, %@", error, [error localizedDescription]);
    };

    [assetsLibrary_ assetForURL:[NSURL URLWithString:flower.imagePath] 
                    resultBlock:resultBlock
                   failureBlock:failureBlock];
}

-[ALAssetsLibrary assetForURL:resultBlock:failureBlock] runs asynchronously. That means that the call returns immediately in your tableView:cellForRowAtIndexPath: method. The cell is displayed in the table view before the actual loading of the asset has taken place.

What you need to do is set the image for the cell in the result block. Something like this:

if (flower.imagePath && ![flower.imagePath isEqualToString:@""])
{
    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *asset)
    {
        NSLog(@"This debug string was logged after this function was done");
        [cell.imageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];

        //this line is needed to display the image when it is loaded asynchronously, otherwise image will not be shown as stated in comments
        [cell setNeedsLayout]; 

    };

    ALAssetsLibraryAccessFailureBlock failureBlock  = ^(NSError *error)
    {
        NSLog(@"Unresolved error: %@, %@", error, [error localizedDescription]);
    };

    [assetsLibrary_ assetForURL:[NSURL URLWithString:flower.imagePath] 
                    resultBlock:resultBlock
                   failureBlock:failureBlock];
}
半夏半凉 2024-12-14 09:40:50

溢出主义者让我提出以下解决方案:

不要在 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath 中创建单元格,而是

创建一个填充有 UITableViewCells 的 NSMutableArray (与您在 cellForRowAtIndexPath 方法中创建的单元格相同)您想要在表格中显示的内容
并简单地在 cellForRowAtIndexPath 方法中返回相关的 UITableViewCell (这将是 NSMutableArray 中的一个对象)。

这样,cellForRowAtIndexPath 方法将显示已经加载并准备显示的单元格。

Fellow Overflowist let me propose the following solution:

rather than creating your cells in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath

create an NSMutableArray populated with UITableViewCells (the same ones you create in the cellForRowAtIndexPath method) that you want to display in the table
and simply return the relevant UITableViewCell (which will be an object in the NSMutableArray) in the cellForRowAtIndexPath method.

This way the cellForRowAtIndexPath method will show cells which have already been loaded and are ready to be shown.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文