将ALAsset保存到SQLite3数据库 - 检索错误

时间:2014-04-02 15:06:32

标签: sqlite alassetslibrary

我试图保存要在sqllite3数据库中上传的资产列表,但是当我解析数据库并将资产设置为数组时,请尝试使用资产我得到一个{ {1}}错误。

SIGABRT

我将ALAsset *asset = (ALAsset *) assets[indexPath.row]; cell.textLabel.text = [NSString stringWithFormat:@"image%d: ready to upload.",indexPath.row]; cell.detailTextLabel.text = @"1.3MB to folder <server folder>"; [[cell imageView] setImage:[UIImage imageWithCGImage:[asset thumbnail]]];// SIGABRT ERROR 作为字符串(TEXT)保存到数据库ALAsset

UTF8formatting

在上面的代码中我试过:

NSMutableArray *tmpArray = [NSMutableArray alloc]init];
///get sql
[tmpArray addObject:someStringFromSQL];
///end sql loop

assets = [tmpArray mutableCopy];

那并没有用。

这是错误:

 [[cell imageView] setImage:[UIImage imageWithCGImage:[(ALAsset *) asset thumbnail]]];// SIGABRT ERROR

有什么建议吗?

另外作为一个附带问题:有谁知道如何从资产中获取文件大小(即1.3MB)?

BLOCK:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString thumbnail]: unrecognized selector sent to instance 0xc0a7800'

2 个答案:

答案 0 :(得分:1)

您必须浏览与保存和检索功能相关的所有代码库。

但是,这里有一些很好的提示。

  1. 保存ALAsset个网址,而不是将整个ALAsset保存为字符串。
  2. 从数据库中检索ALAsset Url并将其转换为NSUrlString。
  3. 使用ALAsset Library加载图像或缩略图。
  4. 希望这会对你有所帮助。

答案 1 :(得分:1)

您的代码示例存在一些问题:

  1. 图像检索是异步发生的,因此当您尝试更新图像时,您需要确保单元格仍然可见(并且不会重复用于其他NSIndexPath)。

    在这种情况下,ALAssetsLibrary的检索可能会非常快,以至于这并不重要,但这是一种熟悉的好模式,因为如果你曾经通过互联网检索图像,这个问题变得越来越重要。

  2. 由于单元格正在被重用,如果您没有立即找到图像并且必须异步更新它,请确保在启动异步过程之前重置UIImageView。否则,你会看到用新的图像替换旧图像的“闪烁”。

  3. 您正在为您的手机使用UITableViewCell。问题在于,它会根据时间cellForRowAtIndexPath完成时图像的大小来布局单元格。

    这有两个简单的解决方案。首先,您可以将单元格的imageView初始化为正确大小的占位符图像。 (我通常有一个名为placeholder.png的图像,它全部为白色或全部透明,我添加到我的项目中,这是我在下面使用的。)这将确保单元格正确布局,以便在异步时稍后设置图像,细胞将已经正确布局。

    其次,您可以使用预先修复布局的自定义单元格,绕过标准UITableViewCell的烦恼,其布局取决于使用的初始图像。

  4. 我建议使用NSCache来保存缩略图图片。这样可以避免在向前和向后滚动时从ALAssetsLibrary获取缩略图时不断重新检索缩略图。不幸的是,iOS 7打破了一些精彩的NSCache内存压力逻辑,所以我建议一个缓存来响应内存压力,并在必要时自行清除。

  5. 无论如何,把它们放在一起,就会得到类似的东西:

    @interface ViewController ()
    
    @property (nonatomic, strong) NSMutableArray *assetGroups;
    @property (nonatomic, strong) ALAssetsLibrary *library;
    @property (nonatomic, strong) ThumbnailCache *imageCache;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.imageCache = [[ThumbnailCache alloc] init];
    
        self.assetGroups = [NSMutableArray array];
    
        self.library = [[ALAssetsLibrary alloc] init];
        [self.library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            if (!group) {
                [self.tableView reloadData];
                return;
            }
    
            CustomAssetGroup *assetGroup = [[CustomAssetGroup alloc] init];
            assetGroup.name = [group valueForProperty:ALAssetsGroupPropertyName];
            assetGroup.assetURLs = [NSMutableArray array];
    
            [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
                if (result) {
                    [assetGroup.assetURLs addObject:[result valueForProperty:ALAssetPropertyAssetURL]];
                }
            }];
    
            [self.assetGroups addObject:assetGroup];
        } failureBlock:^(NSError *error) {
            NSLog(@"%s: enumerateGroupsWithTypes error: %@", __PRETTY_FUNCTION__, error);
        }];
    }
    
    #pragma mark - UITableViewDataSource
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return self.assetGroups.count;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        CustomAssetGroup *group = self.assetGroups[section];
        return [group.assetURLs count];
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        CustomAssetGroup *group = self.assetGroups[section];
        return group.name;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *cellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
        // note, these following three lines are unnecessary if you use cell prototype in Interface Builder
    
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }
    
        CustomAssetGroup *group = self.assetGroups[indexPath.section];
        NSURL *url = group.assetURLs[indexPath.row];
        NSString *key = [url absoluteString];
        UIImage *image = [self.imageCache objectForKey:key];
    
        if (image) {
            cell.imageView.image = image;
        } else {
            UIImage *placeholderImage = [UIImage imageNamed:@"placeholder.png"];
            cell.imageView.image = placeholderImage;  // initialize this to a placeholder image of the right size
    
            [self.library assetForURL:url resultBlock:^(ALAsset *asset) {
                UIImage *image = [UIImage imageWithCGImage:asset.thumbnail];   // note, use thumbnail, not fullResolutionImage or anything like that
    
                [self.imageCache setObject:image forKey:key];
    
                // see if the cell is still visible, and if so, update it
                // note, do _not_ use `cell` when updating the cell image, but rather `updateCell` as shown below
    
                UITableViewCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath]; // not to be confused with similarly named table view controller method ... this one checks to see if cell is still visible
                if (updateCell) {
                    [UIView transitionWithView:updateCell.imageView duration:0.1 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                        updateCell.imageView.image = image;
                        updateCell.textLabel.text = asset.defaultRepresentation.filename;
                    } completion:nil];
                }
            } failureBlock:^(NSError *error) {
                NSLog(@"%s: assetForURL error: %@", __PRETTY_FUNCTION__, error);
            }];
        }
    
        return cell;
    }
    @end
    

    以上使用以下类:

    /** Thumbnail cache
     *
     * This cache optimizes retrieval of old thumbnails. This purges itself 
     * upon memory pressure and sets a default countLimit.
     */
    @interface ThumbnailCache : NSCache
    
    // nothing needed here
    
    @end
    
    @implementation ThumbnailCache
    
    /** Initialize cell
     *
     * Add observer for UIApplicationDidReceiveMemoryWarningNotification, so it purges itself under memory pressure
     */
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
            self.countLimit = 50;
        };
        return self;
    }
    
    /** Dealloc
     *
     * Remove observer before removing cache
     */
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    
    @end
    

    /** Custom AssetGroup object
     *
     * This is my model object for keeping track of the name of the group and list of asset URLs.
     */
    @interface CustomAssetGroup : NSObject
    
    @property (nonatomic, copy)   NSString       *name;
    @property (nonatomic, strong) NSMutableArray *assetURLs;
    
    @end
    
    @implementation CustomAssetGroup
    
    // nothing needed here
    
    @end