简体   繁体   English

将图像从素材资源库加载到UICollectionView

[英]Loading images from Asset library to a UICollectionView

I'm using ELCImagePicker https://github.com/B-Sides/ELCImagePickerController in order to pick my images from the phone's library. 我正在使用ELCImagePicker https://github.com/B-Sides/ELCImagePickerController以便从手机库中选择我的图像。 ELC has two options to return, the first is the UIImage itself (which I don't want as it crashes due to memory when picking more than 5 images). ELC有两个选项可以返回,第一个是UIImage本身(我不希望这样,因为在选择5个以上图像时由于内存而导致崩溃)。 The second is the asset location of the image, this is good for the memory, although my problem is while showing the images on the collection view. 第二个是图像的资产位置,这对内存很有用,尽管我的问题是在集合视图上显示图像时。

So I have this piece of code that works fine and shows the images, but when I scroll up and down through the collection view, it lags a bit. 因此,我有一段可以正常工作并显示图像的代码,但是当我在集合视图中上下滚动时,它会滞后一些。 I assume it's because every time it wants to load a cell it has to go through a block and its asynchronous. 我认为这是因为每次要加载单元时,都必须经历一个块及其异步过程。 I'm trying to find a way to remove the lag and make it scroll smoothly. 我正在尝试找到一种方法来消除滞后并使其平滑滚动。

Any help would be much appreciated. 任何帮助将非常感激。 :) :)

 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

 [library assetForURL:_chosenImages[indexPath.row] resultBlock:^(ALAsset *asset) {

    UIImage *image = [UIImage imageWithCGImage:asset.thumbnail];
  // I believe the problem is here..
    [myCell.imageView setImage:image];
} failureBlock:^(NSError *error) {
    NSLog(@"An error occurred while loading image: %@", error.description);
}];

In the - (void)selectedAssets:(NSArray *)assets method in ELCImagePickerController.m you will be able to see this line ELCImagePickerController.m- (void)selectedAssets:(NSArray *)assets方法中,您将能够看到此行

ALAsset *asset = elcasset.asset;

after this line, there is a dictionary created which then addd to returnArray . 在这行之后,创建了一个字典,然后将其returnArrayreturnArray Skip this dictionary creation part. 跳过此字典创建部分。 Add the asset to the returnArray directly. 将资产直接添加到returnArray中。 change the for method to look like this: 将for方法更改为如下所示:

for(ELCAsset *elcasset in assets) {
    ALAsset *asset = elcasset.asset;
    [returnArray addObject:asset];  
}

Have fun. 玩得开心。

***EDIT*** Also please create a singleton to maintain the life of the AssetLibrary in ELCAlbumPickerController . *** ***编辑请还创建一个单独维持生活AssetLibraryELCAlbumPickerController

First of all, ALAssetsLibrary doesn't guarantee that the result block is called on the main thread. 首先, ALAssetsLibrary不保证在主线程上调用结果块。 You should do the expensive stuff (generating the UIImage ) on a background thread, and any UI work should be done on the main thread. 您应该在后台线程上执行昂贵的工作(生成UIImage ),并且任何UI工作都应在主线程上完成。 So you need to fix that first: 因此,您需要先解决此问题:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    UIImage *image = [UIImage imageWithCGImage:asset.thumbnail];

    dispatch_async(dispatch_get_main_queue(), ^{
        [myCell.imageView setImage:image];
    });
});

Second of all, when you finally get to myCell , this cell is no longer guaranteed to have the same content. 第二,当您最终进入myCell ,不再保证此单元格具有相同的内容。 This is because cells are reused during scrolling. 这是因为在滚动过程中会重复使用单元格。 So you need to get the correct cell. 因此,您需要获取正确的单元格。

One common approach is to use the indexPath : 一种常见的方法是使用indexPath

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    UIImage *image = [UIImage imageWithCGImage:asset.thumbnail];

    dispatch_async(dispatch_get_main_queue(), ^{
        MyUICollectionViewCellSubclass *correctCell = (MyUICollectionViewCellSubclass *)[self.collectionView cellForItemAtIndexPath:indexPath];
        [correctCell.imageView setImage:image];
    });
});

However, this will only work if the index paths are guaranteed not to change which may or may not be the case depending on your use case. 但是,这仅在保证索引路径不改变的情况下才有效,根据您的使用情况,索引路径可能会也可能不会改变。 For example, if the user can insert or delete items, you'll need to take a different (but similar) approach. 例如,如果用户可以插入或删除项目,则需要采取其他(但类似的)方法。

Finally, make sure to nil out imageView 's image when reusing a cell (so you don't show old images as the cells scroll in.) 最后,确保nilimageViewimage重复使用电池时(这样你就不会显示旧图像的细胞滚动。)


Also, it's been a while since I used the assets library, but I think you shouldn't use imageWithCGImage: but rather imageWithCGImage:scale:orientation: . 另外,自从我使用资产库以来已经有一段时间了,但是我认为您不应该使用imageWithCGImage:而是imageWithCGImage:scale:orientation: I believe the method you're currently using will look blurry on Retina devices, and might get the orientation wrong. 我相信您当前使用的方法在Retina设备上看起来会模糊,并且可能会弄错方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM