iOS存取照片到自定义相册以及从相册取照片

因为iOS系统相册权限及照片显示的问题,所以没法像android一样直接在某个路径下创建文件夹存储照片,并利用名字来取照片。iOS实现存储照片到自定义相册,其实是先把图片存到系统相册,然后创建一个相薄,在从系统相册中取出那张照片添加到自定义的相薄中。

使用框架

1.AssetsLibrary,这个框架在iOS9之后废弃掉了,所以建议大家用第二种方法
2.Photos,这个从iOS8之后就可以使用,取代了AssetsLibrary

框架中的类与参数介绍

· PHAssetCollection 图片的集合,其实就是指的一个相册,不管是系统的还是自定义的
· PHFetchResult 表示该相册中的资源的集合
· PHAsset 表示这个相册中的某一个资源,可以是图片或者视频,上面的PHFetchResult其实就相当于一个数组,而PHAsset就相当于数组中的子元素
· localIdentifier PHObject中的一个参数,某个对象的唯一标识符,想要找到相册中存取的某张照片,可以通过这个id遍历查找,其实就像手机的UDID,唯一标识你这个手机

代码块

保存照片到自定义相册

//MARK: -将图片保存到自定义相册中
-(void)saveImageToCustomAblum
{
    //将图片保存到系统的相册
    PHFetchResult *assets = [self saveImageWithPhotos];
    if (assets == nil)
    {
        //自已封装一个debug模式下的log,不然到时候上线还要注释掉
        DLog(@"保存失败");
        return;
    }    
       //创建自定义相册(自己命名,如果没有则创建)    
       PHAssetCollection *assetCollection = [self getAssetCollectionAppNameAndCreate];
    if (assetCollection == nil) {
        DLog(@"相册创建失败");
        return;
    }    
    //将刚才保存到系统相册的图片添加到自定义相册中 
    NSError *error = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        //选取自定义相册进行操作
        PHAssetCollectionChangeRequest *collectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
        //插入图片到自定义相册
        PHFetchResult *assetCount = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];

        [collectionChangeRequest insertAssets:assets atIndexes:[NSIndexSet indexSetWithIndex:assetCount.count]];
        //取出保存的那个对象(图片)
        PHAsset *ass = [assets objectAtIndex:0];
        NSString *aaa = [ass localIdentifier];
        //暂存一下图片的id,后面需要通过id取出照片(你可以存一个数组,也可以取出多张照片,这里就说一下取出单张的)
        [[NSUserDefaults standardUserDefaults] setObject:aaa forKey:kAssetID];
    } error:&error];   
    if (error) {
        DLog(@"保存失败");
        return;
    }
    DLog(@"保存成功");
}

1.保存图片到系统的相册中,返回结果是保存成功后的图片集合

-(PHFetchResult *)saveImageWithPhotos
{
    __block NSString *createdAssetID = nil;    
    NSError *error = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        //获取图片的id
        createdAssetID = [PHAssetChangeRequest             creationRequestForAssetFromImage:_imm].placeholderForCreatedAsset.localIdentifier;
    } error:&error];

    if (error) {
        return nil;
    }
    //获取保存到系统相册成功后的 asset 对象集合(一张图片也是返回一个集合)
    PHFetchResult *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetID] options:nil];
    return assets;
}

2.判断有没有拥有与你设定的名字同名的自定义相册(如果没有则创建)

-(PHAssetCollection *)getAssetCollectionAppNameAndCreate
{
    //设置你想要创建的相册的名字
    NSString *title = @"我的新建相册";
    //获取与要创建的相册同名的自定义相册
    PHFetchResult *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    for (PHAssetCollection *collection in collections) {
        //遍历
        if ([collection.localizedTitle isEqualToString:title]) {
            //找到了同名的自定义相册,返回
            return collection;
        }
    }

    //程序走到这,说明没有找到自定义的相册,需要创建
    NSError *error = nil;
    __block NSString *createID = nil; //用来获取创建好的相册
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        //发起了创建新相册的请求,并拿到相册的id,当前并没有创建成功,待创建成功后,通过id来获取创建好的自定义相册
        PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
        createID = request.placeholderForCreatedAssetCollection.localIdentifier;
    } error:&error];
    if (error) {
        DLog(@"创建失败");
        return nil;
    }else{
        DLog(@"创建成功");
        [[NSUserDefaults standardUserDefaults] setObject:createID forKey:kAlbumID];
        //通过id获取创建完成的相册
        return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createID] options:nil].firstObject;
    }   
}

从相册中取照片

1.先通过你自定义的相册的名字,找到这个PHAssetCollection
2.找到你的PHAssetCollection(自定义相册)之后,通过遍历相册集合,根据id值判断是否有匹配的图片

//通过 相薄名字查找新建相册
var albumColl = PHAssetCollection()
let collections:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: nil)
for j in 0..let collection:PHAssetCollection = collections[j] as! PHAssetCollection
    if collection.localizedTitle == "我的新建相册" {
        //找到了同名的自定义相册,返回
        albumColl = collection
        break
    }
}
let picAssets:PHFetchResult = PHAsset.fetchAssetsInAssetCollection(albumColl, options: nil)
//遍历assets集合,找到id值一样的图片取出来
for i in 0..let asset:PHAsset = picAssets[i] as! PHAsset
    if asset.localIdentifier == (NSUserDefaults.standardUserDefaults().objectForKey("assetId") as! String)! {
        PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: { (result: UIImage?, dictionry: Dictionary?) in
            //根据result取出这张照片            
            if result != nil && result != NSNull() {
                self.albumIma = result!
            } else {
                self.albumIma = UIImage.init(named: "pic_loading")!
            }
        })
    }
}

注意

自定义相册里面的照片,其实相当于系统相册中图片的一个影子,系统相册里的图片没了,影子也就不存在了。因为每次拍照存放照片,实际上先存放到系统相册,然后从系统相册插入过去的;再删除照片的时候,系统相册的删除了,两个相册的照片就全没了,但是自定义相册里的照片删除,系统相册的照片则无影响


多说一句,假如你把每次拍照的图片都存放到一个本地文件或者小型的SQL数据库里面,进行持久化存储了,那么一定要在程序每次进入活跃状态的时候,检测自定义相册中的图片和数据库中的是否匹配,不匹配就删除本地多余的照片,这样才能做到实时对应。至于检测匹配就不要用两个for in嵌套了(时间复杂度O(m*n)),通过两个哈希序列进行比较是比较简单的做法(时间复杂度O(m+n))。

你可能感兴趣的:(iOS)