1. 程式人生 > >iOS存取照片到自定義相簿以及從相簿取照片

iOS存取照片到自定義相簿以及從相簿取照片

因為iOS系統相簿許可權及照片顯示的問題,所以沒法像android一樣直接在某個路徑下建立資料夾儲存照片,並利用名字來取照片。iOS實現儲存照片到自定義相簿,其實是先把圖片存到系統相簿,然後建立一個相薄,在從系統相簿中取出那張照片新增到自定義的相薄中。

使用框架

1.AssetsLibrary,這個框架在iOS9之後廢棄掉了,所以建議大家用第二種方法
2.Photos,這個從iOS8之後就可以使用,取代了AssetsLibrary

框架中的類與引數介紹

· PHAssetCollection 圖片的集合,其實就是指的一個相簿,不管是系統的還是自定義的
· PHFetchResult

表示該相簿中的資源的集合
· PHAsset 表示這個相簿中的某一個資源,可以是圖片或者視訊,上面的PHFetchResult其實就相當於一個數組,而PHAsset就相當於陣列中的子元素
· localIdentifier PHObject中的一個引數,某個物件的唯一識別符號,想要找到相簿中存取的某張照片,可以通過這個id遍歷查詢,其實就像手機的UDID,唯一標識你這個手機

程式碼塊

儲存照片到自定義相簿

//MARK: -將圖片儲存到自定義相簿中
-(void)saveImageToCustomAblum
{
    //將圖片儲存到系統的相簿
    PHFetchResult<PHAsset *> *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<PHAsset *> *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<PHAsset *> *)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<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetID] options:nil];
    return assets;
}

2.判斷有沒有擁有與你設定的名字同名的自定義相簿(如果沒有則建立)

-(PHAssetCollection *)getAssetCollectionAppNameAndCreate
{
    //設定你想要建立的相簿的名字
    NSString *title = @"我的新建相簿";
    //獲取與要建立的相簿同名的自定義相簿
    PHFetchResult<PHAssetCollection *> *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..<collections.count {
    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..<picAssets.count {
    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))。