iOS - 選取相冊中iCloud雲上圖片和視頻的處理

關於iOS選取相冊中iCloud雲上圖片和視頻

 推薦看: TZImagePickerController的源碼,這個是一個很是靠譜的相冊選擇圖片視頻的庫 。固然也能夠本身寫 以下遇到的問題

工做緣由,須要處理接入一個視頻模塊,在視頻選擇的時候遇到了一個不太容易發現的bug,產生的緣由是因爲手機內存小,而用戶又打開了相冊同步iCloud,git

 

加載中的圖片github

 

在這時,若是本地可用內存太小,會致使
將本地相冊中的圖片或視頻刪除只留縮略圖,若是App調用的時候想要選取這種圖片就須要從iCloud雲中進行下載,
才能獲取原圖或原視頻。ide

下面po下解決方案:fetch

若是你以前處理過相冊問題,那麼對以下的代碼確定不陌生,就是很普通的兩個系統級別的請求回調,獲取對應的圖片,視頻。atom

// get Image
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {

}];
// get Video
[[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
    if (completion) completion(playerItem,info);
}];

 

可是每每以前沒有注意到第二個輸入 options 是用來幹嗎的,
其實解決方案就來自於這個 PHImageRequestOptionsPHVideoRequestOptionsspa

這這兩個 options 都有一個共同的參數就是.net

@property (nonatomic, assign, getter=isNetworkAccessAllowed) BOOL networkAccessAllowed;
// if necessary will download the image from iCloud (client can monitor or cancel using progressHandler). Defaults to NO (see start/stopCachingImagesForAssets)

 

系統的解釋也很詳細,若是賦值 YES ,那麼容許從 iCloud 中獲取圖片和視頻,默認是 NO線程

雖然這個問題解決不是很難,可是每每容易被忽略,因此記錄一下。code

這裏很是感謝@半遲塵大大的TZImagePickerController的源碼,這個是一個很是靠譜的相冊選擇圖片視頻的庫,而且處於仍在維護中。感興趣的能夠連接過去看一看源碼,寫的很好。orm

博主博客@HarwordLiu

下面po一下完整的這個問題的解決代碼:

/// Get Video
- (void)getVideoOutputPathWithAsset:(PHAsset *)asset completion:(void (^)(NSString *outputPath))completion {
    PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
    options.version = PHVideoRequestOptionsVersionOriginal;
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    options.networkAccessAllowed = YES;
    [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
        // NSLog(@"Info:\n%@",info);
        AVURLAsset *videoAsset = (AVURLAsset*)avasset;
        // NSLog(@"AVAsset URL: %@",myAsset.URL);
        [self startExportVideoWithVideoAsset:videoAsset completion:completion];
     }];
}
/// Get Image

- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {

    PHAsset *phAsset = (PHAsset *)asset;
    CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight;
    CGFloat pixelWidth = photoWidth * 2.0;
    CGFloat pixelHeight = pixelWidth / aspectRatio;
    CGSize imageSize = CGSizeMake(pixelWidth, pixelHeight);

    // 修復獲取圖片時出現的瞬間內存太高問題
    PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
    option.resizeMode = PHImageRequestOptionsResizeModeFast;
    PHImageRequestID imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
        if (downloadFinined && result) {
            if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
        }
        // Download image from iCloud / 從iCloud下載圖片
        if ([info objectForKey:PHImageResultIsInCloudKey] && !result) {
            PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
            option.networkAccessAllowed = YES;
            option.resizeMode = PHImageRequestOptionsResizeModeFast;
            [[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
                if (completion) completion(resultImage,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);

            }];
        }
    }];
    return imageRequestID;
}

 

判斷是不是iCloud視頻或圖片的方法

https://stackoverflow.com/questions/31966571/check-given-phasset-is-icloud-asset

第一種方法

[cloudAlbums enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop)
{
    PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions];
    [result enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop)
    {  
        PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
        options.resizeMode = PHImageRequestOptionsResizeModeFast;
        options.synchronous = YES;
__block BOOL isICloudAsset
= NO; [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) { //根據請求會調中的參數重 NSDictionary *info 是否有cloudKey 來判斷是不是 iCloud if ([info objectForKey: PHImageResultIsInCloudKey].boolValue) { isICloudAsset = YES; } }]; }]; }];

 

 

第二種方法(實際上是同一種)

__block BOOL isPhotoInICloud = NO;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.networkAccessAllowed = YES;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
// 下載iCloud 圖片的進度回調 只要圖片是在icloud中 而後去請求圖片就會走這個回調 若是圖片沒有在iCloud中不回走這個回調
//裏面的會調中的參數重 NSDictionary *info 是否有cloudKey 來判斷是不是  iCloud 處理UI放到主線程
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info){

        isPhotoInICloud = YES;
});

//上面的進度下載完了以後纔會掉用resultHandler 回調
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {

        if (isPhotoInICloud) {
            // Photo is in iCloud.
        }
});
相關文章
相關標籤/搜索