自定義相機、相冊(相冊篇)

工作之余,研究了一下相機與相冊的自定義,在這里整理成篇僅供參考學習,希望可以給大家帶來些許幫助,也期待大家的批評指正。

自定義相冊

GIF 示例:


ccpcamera.gif

DEMO下載地址:https://github.com/IMCCP/CCPCustomCamera

在 iOS 設備中,照片是相當重要的一部分。在 iOS8.0之前,開發者只能使用 AssetsLibrary 框架來訪問設備的照片庫。而在 iOS8 之后,蘋果提供了一個名為 PhotoKit 的框架,一個可以讓應用更好地與設備照片庫對接的框架.由于市面上有一部分應用還支持iOS7,同時為了更加全面的學習,在這里將整理AssetsLibrary 框架與 PhotoKit 框架的相關知識,供大家參考學習.

一、AssetsLibrary 基本介紹

AssetsLibrary: 代表整個設備中的資源庫(照片庫),通過 AssetsLibrary 可以獲取和包括設備中的照片和視頻

ALAssetsGroup: 映射照片庫中的一個相冊,通過 ALAssetsGroup 可以獲取某個相冊的信息,相冊下的資源,同時也可以對某個相冊添加資源。

ALAsset: 映射照片庫中的一個照片或視頻,通過 ALAsset 可以獲取某個照片或視頻的詳細信息,或者保存照片和視頻。

ALAssetRepresentation: ALAssetRepresentation 是對 ALAsset 的封裝(但不是其子類),可以更方便地獲取 ALAsset 中的資源信息,每個 ALAsset 都有至少有一個 ALAssetRepresentation 對象,可以通過 defaultRepresentation 獲取。

二、PhotoKit 基本介紹

PhotoKit 是一套比 AssetsLibrary 更完整也更高效的庫,對資源的處理跟 AssetsLibrary 也有很大的不同。

PhotoKit 基本構成的介紹:

PHAsset: 代表照片庫中的一個資源,跟 ALAsset 類似,通過 PHAsset 可以獲取和保存資源
PHFetchOptions: 獲取資源時的參數,可以傳 nil,即使用系統默認值
PHAssetCollection: PHCollection 的子類,表示一個相冊或者一個時刻,或者是一個「智能相冊(系統提供的特定的一系列相冊,例如:最近刪除,視頻列表,收藏等等,如下圖所示)
PHFetchResult: 表示一系列的資源結果集合,也可以是相冊的集合,從PHCollection 的類方法中獲得
PHImageManager: 用于處理資源的加載,加載圖片的過程帶有緩存處理,可以通過傳入一個 PHImageRequestOptions 控制資源的輸出尺寸等規格
PHImageRequestOptions: 如上面所說,控制加載圖片時的一系列參數

三、主要功能

1.獲取相冊圖片資源;
2.自定義相冊功能;
3.圖片瀏覽器功能;
4.主要 工具類 介紹:

a.CCPPhotoAlbumViewController 控制器 主要要來進行相冊資源的讀?。?/p>

- (void)viewDidLoad {
    [super viewDidLoad];
    [self makeUI];
    //進行系統型號的判斷,調用不同的圖庫處理框架
    if ([self iOSIsbefore_iOS8]) {
        [self iOSBefore_iOS8];
    } else {
        [self iOSAfter_iOS8];
    }
}
//系統版本小于8.0
- (void) iOSBefore_iOS8 {
    //提示
    NSString *tipTitle = nil;
    //相冊的訪問狀態
    ALAuthorizationStatus authorizationStatus = [ALAssetsLibrary authorizationStatus];
    /* 獲取當前應用對照片的訪問授權狀態
     ALAuthorizationStatusNotDetermined = 0, // 用戶還沒有做出選擇這個應用程序的問候
     ALAuthorizationStatusRestricted,        // 這個應用程序沒有被授權訪問照片數據。當前用戶不能改變應用程序的狀態,是受限制的。如家長控制權限
     ALAuthorizationStatusDenied,            // 用戶已拒絕該應用程序訪問照片數據
     ALAuthorizationStatusAuthorized         // 用戶已授權該應用可以訪問
     */
    
    // 如果沒有獲取訪問授權,或者訪問授權狀態已經被明確禁止,則顯示提示語,引導用戶開啟授權
    if (authorizationStatus == ALAuthorizationStatusRestricted || authorizationStatus == ALAuthorizationStatusDenied) {
        NSDictionary *mainInfoDictionary = [[NSBundle mainBundle] infoDictionary];
        NSString *myAppName = [mainInfoDictionary objectForKey:@"CFBundleDisplayName"];
        tipTitle = [NSString stringWithFormat:@"請在設備的\"設置-隱私-照片\"選項中,允許%@訪問你的手機相冊", myAppName];
    } else {
        
        [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            
            if (group) {
                [group setAssetsFilter:[ALAssetsFilter allPhotos]];
                if (group.numberOfAssets > 0) {
                    // 把相冊儲存到數組中,方便后面展示相冊時使用
                    [self.assetsArray addObject:group];
                    [self.nameArray addObject:[group valueForProperty:ALAssetsGroupPropertyName]];
                    //獲取相冊封面圖
                    UIImage *posterImage =  [UIImage imageWithCGImage:[group posterImage]];
                    [self.posterImageArray addObject:posterImage];
                    
                }
                
            } else {
                
                if ([self.assetsArray count] > 0) {
                    // 把所有的相冊儲存完畢,可以展示相冊列表
                } else {
                    // 沒有任何有資源的相冊,輸出提示
                }
            }
            
            
        } failureBlock:^(NSError *error) {
            
            NSLog(@"Asset group not found!\n");
            
        }];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.showTableView reloadData];
        });
        
    }
}
//系統版本號大于等于8.0
- (void) iOSAfter_iOS8 {
    /*
     PHAssetCollectionTypeAlbum      自建相冊
     PHAssetCollectionTypeSmartAlbum 智能相冊
     PHAssetCollectionTypeMoment     時刻相冊
     
     智能相冊子類型
     PHAssetCollectionSubtypeSmartAlbumGeneric    通用的
     PHAssetCollectionSubtypeSmartAlbumPanoramas  全景
     PHAssetCollectionSubtypeSmartAlbumVideos     視屏
     PHAssetCollectionSubtypeSmartAlbumFavorites  收藏
     PHAssetCollectionSubtypeSmartAlbumTimelapses 延時視屏,也會在PHAssetCollectionSubtypeSmartAlbumVideos在出現
     PHAssetCollectionSubtypeSmartAlbumAllHidden  隱藏的
     PHAssetCollectionSubtypeSmartAlbumRecentlyAdded 最近添加
     PHAssetCollectionSubtypeSmartAlbumBursts    連拍
     PHAssetCollectionSubtypeSmartAlbumSlomoVideos Slomo是slow motion的縮寫,高速攝影慢動作解析
     PHAssetCollectionSubtypeSmartAlbumUserLibrary 用戶所有的資源
     PHAssetCollectionSubtypeSmartAlbumSelfPortraits 所有前置攝像頭拍的照片和視屏
     PHAssetCollectionSubtypeSmartAlbumScreenshots 所有的截屏圖
     */
    //權限
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusDenied || status == PHAuthorizationStatusRestricted) {
        [self noticeAlerPhotos];
    }else{
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) {
                
                PHFetchOptions *option = [[PHFetchOptions alloc] init];
                //排序方式
                option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:NO]];
                // 列出所有相冊智能相冊
                PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
                
                for (NSInteger i = 0; i < smartAlbums.count; i++) {
                    // 獲取一個相冊(PHAssetCollection)
                    PHCollection *collection = smartAlbums[i];
                    if ([collection isKindOfClass:[PHAssetCollection class]]) {
                        PHAssetCollection *assetCollection = (PHAssetCollection *)collection;
                        // 從每一個智能相冊中獲取到的 PHFetchResult 中包含的才是真正的資源(PHAsset)
                        PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
                        
                        if (fetchResult.count > 0) {
                            
                            [self.assetsArray addObject:fetchResult];
                            
                            [self.nameArray addObject:assetCollection.localizedTitle];
                            //獲取封面圖片,就是第一張圖片
                            PHAsset *asset = (PHAsset *)fetchResult.firstObject;
                            PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
                            //默認的是異步加載,這里選擇了同步 
                            options.synchronous = YES;
                           //PHImageManagerMaximumSize:獲取原圖,占用很大內存 建議不要使用
                            [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info)
                             {
                                 [self.posterImageArray addObject:result];
                             }];
                        }
                    }else {
                        
                        NSAssert(NO, @"Fetch collection not PHCollection: %@", collection);
                    }
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.showTableView reloadData];
                    });
                }
            }
        }];
        
    }
    
    // 獲取所有資源的集合,并按資源的創建時間排序
    //    PHFetchOptions *options = [[PHFetchOptions alloc] init];
    //    options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
    //    PHFetchResult *assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];
    //
    //    // 這時 assetsFetchResults 中包含的,應該就是各個資源(PHAsset)
    //    for (NSInteger i = 0; i < assetsFetchResults.count; i++) {
    //        // 獲取一個資源(PHAsset)
    //        PHAsset *asset = assetsFetchResults[i];
    //    }
    //
    //    NSLog(@"%@",assetsFetchResults);
    
}

b.CCPShowPhotoVC 控制器 主要用于獲取到的對應照片的展示
如圖:

CCPShowPhotoVC.jpg

c.XLPhotoBrowser 主要用于圖片的瀏覽
本著不重復造輪子的原則,demo中圖片瀏覽器使用了 XLPhotoBrowser
XLPhotoBrowser下載地址:https://github.com/Shannoon/XLPhotoBrowser

在這里對框架作者表示感謝!

四、參考:

a.http://kayosite.com/ios-development-and-detail-of-photo-framework.html

b.[http://www.lxweimin.com/p/535bfe3c328f](http://www.lxweimin.com/p/535bfe3c3

c.http://www.lxweimin.com/p/cc85282fac5e

d. http://www.cnblogs.com/Jenaral/p/5580497.html

在這里對blog作者表示感謝!

由于篇幅有限,在這里不再詳細的展開,demo中對一些坑點都做了詳細的注釋,如果您有需要可下載demo進行查看.

感謝您的閱讀,期待您的 Star,如果在使用中您有任何問題,可以在 github issue,我會盡自己能力給您答復 。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容

  • 【原創圖文】一座城市一個人,也許你會覺得略顯孤獨。但生活往往就這樣,很多事情總是需要一個人面對。一個人坐公交、一個...
    一奕閱讀 241評論 0 4
  • 發現自己身上一種品質不知道是優點還是缺點,就是固執。 喜歡聽一首歌就會一直單曲循環到再也不聽,喜歡...
    及時行樂諾閱讀 276評論 0 7