1. 程式人生 > 實用技巧 >PhotoKit儲存圖片到相簿

PhotoKit儲存圖片到相簿

我們分為幾個步驟學習

準備工作

  1. 配置info.plist
  2. 引入標頭檔案

在開始開發之前需要進行info.plist的配置,如果不進行配置會拋錯。

<key>NSPhotoLibraryUsageDescription</key>
<string>使用相簿儲存圖片</string>

2019-12-23 09:13:56.301622+0800 ZucheDemo[920:649891] [access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.

在開發之前我們匯入標頭檔案

#import <Photos/Photos.h>

儲存一個圖片到相簿膠捲

此方法可以儲存一張圖片到相機膠捲。

/// 儲存圖片到相機膠捲
- (void)saveImageToCameraRoll:(UIImage *)image {
    //儲存圖片到【相機膠捲】
    [[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
        //非同步執行修改操作
        [PHAssetChangeRequest creationRequestForAssetFromImage:image];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (error) {
            NSLog(@"%@",@"儲存失敗");
        } else {
            NSLog(@"%@",@"儲存成功");
        }
    }];
}

建立一個相簿(以應用名冊命名)

首先我們看如何建立一個相簿

/// 建立以app名字命名的相簿
- (void)createNewCollection {
    NSError *error = nil;
    [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
        //獲取app名字
        NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
        //建立一個【自定義相簿】
        [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
        
    } error:&error];
}

但是這麼簡單的建立相簿,一般不符合需求,一般我們需要先檢視是否已經存在同名相簿。

/// 檢視是否建立了以APP命名的相簿
- (PHAssetCollection *)checkLocalCollection {
    NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
    return [self checkCollection:title];
}

/// 檢視是否建立了以此名字命名的相簿
/// @param title 相簿名字
- (PHAssetCollection *)checkCollection:(NSString *)title {
    //查詢所有【自定義相簿】
    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    PHAssetCollection *createCollection = nil;
    for (PHAssetCollection *collection in collections) {
        if ([collection.localizedTitle isEqualToString:title]) {
            createCollection = collection;
            break;
        }
    }
    return createCollection;
}

所以我們需要先檢視是否存在同名相簿,之後再進行建立相簿

/// 建立一個以APP名字命名的相簿,如果不存在
- (void)createNewCollectionIfNotExist {
    
    NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
    
    PHAssetCollection *createCollection = [self checkCollection:title];
    
    if (createCollection == nil) {
        //當前對應的app相簿沒有被建立
        //建立一個【自定義相簿】
        NSError *error = nil;
        [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
            //建立一個【自定義相簿】
            [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
        } error:&error];
        
    }
    
}

儲存圖片到建立的相簿


/// 儲存圖片到自己建立的相簿
/// @param image 圖片
- (void)savePhotoToAlbum:(UIImage *)image {
    // 1.先儲存圖片到【相機膠捲】
    /// 同步執行修改操作
    NSError *error = nil;
    
    __block PHObjectPlaceholder *placeholder = nil;
    
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
       placeholder =  [PHAssetChangeRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset;
    } error:&error];
    
    if (error) {
        NSLog(@"儲存失敗");
        return;
    }
    
    // 2.檢視是否擁有一個以APP名稱命名的相簿
    PHAssetCollection * assetCollection = [self checkLocalCollection];
    
    if (assetCollection == nil) {
        NSLog(@"獲取相簿失敗");
        return;
    }
    
    // 3.將剛才儲存到【相機膠捲】裡面的圖片引用到【自定義相簿】
    [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
        PHAssetCollectionChangeRequest *requtes = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
        [requtes addAssets:@[placeholder]];
    } error:&error];
    
    if (error) {
        NSLog(@"儲存圖片失敗");
    } else {
        NSLog(@"儲存圖片成功");
    }
}

查詢圖片並顯示

/// 查詢圖片
- (void)fetchPhotoFromLocalCollection {
    
    PHAssetCollection *assetCollection =  [self checkLocalCollection];
    
    if (assetCollection == nil) {
        NSLog(@"獲取相簿失敗");
        return;
    }
    
    PHFetchResult *results = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    
    if (results.count > 0) {
        
        __weak typeof(self) weakSelf = self;
        //獲取最後一個圖片
        PHAsset *asset = results.lastObject;
        //獲取顯示圖片控制元件的大小
        CGSize size = CGSizeMake(CGRectGetWidth(self.imageView.bounds), CGRectGetHeight(self.imageView.bounds));
        //呼叫轉換方法
        [self imageWithAsset:asset size:size resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            if (result) {
                NSLog(@"%@",info);
                weakSelf.imageView.image = result;
            }
            else {
                NSLog(@"轉換圖片失敗");
            }
        }];
    }
    
}

/// asset轉成為image
/// @param asset asset description
/// @param size 圖片尺寸
/// @param resultHandler 結果回撥
- (void)imageWithAsset:(PHAsset *)asset size:(CGSize)size resultHandler:(void(^)(UIImage * _Nullable result, NSDictionary * _Nullable info))resultHandler {
    //option的設定
    PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
    option.resizeMode = PHImageRequestOptionsResizeModeNone;
    
    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:(PHImageContentModeAspectFit) options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        
        if (resultHandler) {
            resultHandler(result,info);
        }
        
    }];
    
}

從相簿中刪除圖片

/// 刪除圖片
- (void)deletePhotoFromLocalCollection {
    
    PHAssetCollection *assetCollection =  [self checkLocalCollection];
    
    PHFetchResult *results = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    
    if (results.count > 0) {
        
        NSError *error = nil;
        
        [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
            
            //刪除時候需要傳入一個PHFetchResulth或者一個數組,遵守這個協議的類<NSFastEnumeration>
            
            //刪除最後一張
            //[PHAssetChangeRequest deleteAssets:@[results.lastObject]];
            
            //刪除整個相簿內的所有圖片
            [PHAssetChangeRequest deleteAssets:results];
            
        } error:&error];
    }
    
}