使用PhotoKit 搭建相冊選擇器(支持多選)

1. 閑談

iOS8 以后蘋果推出新的關(guān)于相冊的框架-PhotoKit,相比較之前的AssetsLibrary 框架有了很大的提升转质,由于初次接觸這個新的框架后裸,也在網(wǎng)上查找了很多大神的博客資料咳榜,本文就淺談一下自己對這個框架的理解做裙。

2.介紹

PhotoKit 主要有PHAsset习瑰、PHFetchOptions者娱、PHFetchResult抡笼、PHAssetCollectionPHImageManager黄鳍、PHCollectionList幾個重要的類推姻。

PHAsset:代表照片庫的一個資源 也就是具體的某一個照片或者視頻。

PHFetchOptions: 獲取資源的參數(shù) 可以為nil

PHFetchResult:表示一系列的資源結(jié)果集合框沟,也可以是相冊的集合 從PHCollection的方法中獲得.

PHAssetCollection: PHCollection的子類藏古,表示一個相冊或者一個時刻(最近刪除增炭、收藏)

PHImageManager:用于處理資源的加載,加載圖片的過程有緩存拧晕,可以使用 PHImageRequestOptions控制資源的輸出尺寸等規(guī)格

PHCollectionList:表示一組PHCollection

3.開始搭建

  • 3.1 由于從相冊獲取照片之后需要展示隙姿,所有首先我們需要創(chuàng)建一個展示你選中照片的界面,因此我使用的是UICollectionView布局界面防症,并自定義了一個UICollectionViewCell 可以實現(xiàn)刪除照片 命名為 - PhotoCell,如下所示:
#import <UIKit/UIKit.h>
#import <Photos/Photos.h>
@class PhotoCell;
@protocol PhotoCellDelegate <NSObject>
/**刪除照片的代理方法*/
-(void)deleteThePhotoForCell:(PhotoCell *)cell  deleteBtn:(UIButton *)btn;
@end

@interface PhotoCell : UICollectionViewCell
/**圖片視圖*/
@property(nonatomic,strong)UIImageView *photoView;
/**刪除按鈕*/
@property(nonatomic,strong)UIButton *deleteBTn;
/**代理*/
@property(nonatomic,weak) id <PhotoCellDelegate> delegate;
@end
  • 3.2 創(chuàng)建一個管理獲取相冊資源的工具類 - YHPhotosData,使用這個工具類實現(xiàn)以下功能:獲取所有相冊列表孟辑、獲取某一個相冊中的照片資源、 將具體某一個照片資源轉(zhuǎn)化為照片蔫敲。
    YHPhotosData.h文件中
#import <Foundation/Foundation.h>
#import <Photos/Photos.h>//系統(tǒng)照片的框架
@interface YHPhotosData : NSObject
//獲取所有的相冊集
+(NSMutableArray *)getAllPhotoListData;
//獲取某一個相冊的所有資源
+(NSMutableArray *)getPhotosForPHAssetCollection:(PHAssetCollection *)collection;
//從相冊的某一個照片資源獲取一張高清照片
-(void)getImageObject:(id)set Complection:(void(^)(UIImage *photo,BOOL isDegraded))complection;
@end

YHPhotosData.m文件中

+(NSMutableArray *)getAllPhotoListData{
   NSMutableArray *dataArray = [NSMutableArray array];
   //1.0列出所有智能相冊
   PHFetchResult *samrtResult  = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
 for(int i = 0 ;i<samrtResult.count; i++) {  
       [dataArray addObject:samrtResult[i]];
   }
  //2.0列出所有的用戶創(chuàng)建的相冊
   PHFetchResult *userResult = [PHAssetCollection fetchTopLevelUserCollectionsWithOptions:nil]; 
   for (PHAssetCollection *sub  in userResult) {
       [dataArray addObject:sub];
   } 
 return dataArray;
}
+(NSMutableArray *)getPhotosForPHAssetCollection:(PHAssetCollection *)collection{
    NSMutableArray *photosArray = [NSMutableArray array];
    //1.獲取了結(jié)果集
    PHFetchResult *photosResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];  
    //2.便利結(jié)果集 取出具體某一張圖片資源  添加在數(shù)組中  
    for(PHAsset *set  in  photosResult){
        if(set.mediaSubtypes == PHAssetMediaSubtypeNone){   
            [photosArray addObject:set];
        }    
    }
    return  photosArray;
}
-(void)getImageObject:(id)set Complection:(void (^)(UIImage *, BOOL))complection
{
    if ([set isEqual:[PHAsset class]]){     
        PHAsset *photoSet = set;
        CGFloat mainWidth = [UIScreen mainScreen].bounds.size.width;
       //1.0算出照片資源自身的比例
        CGFloat setScale = photoSet.pixelWidth/photoSet.pixelHeight;
        //1.1 獲取屏幕比例
        //屏幕分辨率 scale = 1 代表 分辨率是320 * 480; =2 代表 分辨率是 640 * 960; = 3 代表 分辨率是 1242 * 2208
        CGFloat scale = [UIScreen mainScreen].scale;
        //1.2計算照片在不同屏幕上的像素   
        CGFloat pixWidth = mainWidth * scale;
        //1.3根據(jù)圖片自身比例計算照片在屏幕上的高
        CGFloat pixheight = mainWidth/setScale;       
        /**
         *  PHImageManager 是通過請求的方式拉取圖像饲嗽,并可以控制請求得到的圖像的尺寸、剪裁方式奈嘿、質(zhì)量貌虾,緩存以及請求本身的管理(發(fā)出請求、取消請求)等
         *
         *  @param pixelWidth 獲取圖片的寬
         *  @param pixelHeight 獲取圖片的高
         *  @param contentMode 圖片的剪裁方式
         *
         *  @return
         */    
     [[PHImageManager defaultManager] requestImageForAsset:photoSet targetSize:CGSizeMake(pixWidth, pixheight) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
         // 排除取消裙犹,錯誤尽狠,低清圖三種情況,即已經(jīng)獲取到了高清圖
         BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
         if (downloadFinined) {
             //回調(diào)
             if (complection){           
                 complection(result,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
             }
         }
     }]; 
 }
}
  • 3.3 工具類寫完之后叶圃,接下來開始創(chuàng)建相冊列表控制器 PhotosListVC 用來展示所有的相冊列表袄膏,同時自定義Cell(我這里定義的是PhotoListCell)用來顯示每個相冊。cell中顯示的照片就是該相冊中所有照片中的最后一張掺冠。
    PhotoListCell 定義非常簡單沉馆,我在這里就不過多敘述了.
/**圖片視圖*/
@property(nonatomic,strong)UIImageView *photoView;
/**標(biāo)題*/
@property(nonatomic,strong)UILabel *title;

這里比較重要的一個方法就是 給cell設(shè)置默認(rèn)數(shù)據(jù)。既相冊的標(biāo)題 以及顯示的照片(最后一張).

///設(shè)置數(shù)據(jù)
-(void)getImageForAssetCollection:(PHAssetCollection *)coll{  
    //獲取該相冊最后一張照片資源
    PHAsset *set = [[YHPhotosData getPhotosForPHAssetCollection:coll] lastObject] ;   
    //轉(zhuǎn)化為照片  并設(shè)置數(shù)據(jù)  (由于相冊可能沒有照片需要判斷一下德崭,給一張默認(rèn)的照片)          
    [[PHImageManager defaultManager]requestImageForAsset:set targetSize:self.photoView.frame.size contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        if (result == nil) {
            self.photoView.image = [UIImage imageNamed:@"no_data"];
        }else {       
            self.photoView.image = result;
        }
    }];
     self.title.text = coll.localizedTitle;
}
  • 3.4 創(chuàng)建展示相冊所有照片的控制器PhotoShowVC,并自定義個Cell展示照片,這里我自己定義的是PhotosShowCell.
    PhotosShowCell.h
#import <UIKit/UIKit.h>
#import <Photos/Photos.h>
//獲取點擊的照片
typedef void (^PhotosShowCellBlock)(UIImage *image);
@interface PhotosShowCell : UICollectionViewCell
/**選擇按鈕*/
@property(nonatomic,strong)UIButton *selectBTn;
//獲取點擊的那個照片blcok
@property(nonatomic,copy)PhotosShowCellBlock cellBlock;
//設(shè)置數(shù)據(jù)
-(void)setPhotoForPHAsset:(PHAsset *)set;
@end

PhotosShowCell.m

//設(shè)置cell數(shù)據(jù) 傳遞過來的都是一張照片資源  不是照片 需要轉(zhuǎn)化
-(void)setPhotoForPHAsset:(PHAsset *)set{
    [[PHImageManager defaultManager]requestImageForAsset:set targetSize:self.photoView.frame.size contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {  
        if (result) {      
            // 排除取消斥黑,錯誤,低清圖三種情況眉厨,即已經(jīng)獲取到了高清圖
            BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
            if (downloadFinined) {     
                self.photoView.image =result;   
                if (self.cellBlock) {
                  //獲取點擊的照片
                    self.cellBlock(result);
                }
            }          
        }else {
            self.photoView.image = [UIImage imageNamed:@"no_data"];
        }     
    }];
}

在控制器PhotoShowVC創(chuàng)建一個可變數(shù)組selectImageArray存放選中的所有照片锌奴,在cell的點擊方法中 執(zhí)行cell的block方法獲取到點擊的照片, 并存放到數(shù)組selectImageArray中,同時改變cell上按鈕的狀態(tài)憾股。

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    PhotosShowCell *cell  = (PhotosShowCell *)[collectionView cellForItemAtIndexPath:indexPath];
    if (cell.selectBTn.selected) {
        cell.selectBTn.selected = NO;  
        [cell.selectBTn setImage:[UIImage imageNamed:@"select_no"] forState:UIControlStateNormal];
        [self.selectImageArray removeObjectAtIndex:indexPath.row];
    }else {
        cell.selectBTn.selected = YES;
        [cell.selectBTn setImage:[UIImage imageNamed:@"select_yes"] forState:UIControlStateNormal];  
        [cell setPhotoForPHAsset:self.imageArray[indexPath.row]];
         cell.cellBlock = ^(UIImage *image) {
         [self.selectImageArray addObject:image];
        };   
    }
}

然后在控制器PhotoShowVC創(chuàng)建完成鹿蜀、預(yù)覽按鈕以及定義一個返回首頁并傳遞照片到首頁的Blcok ,當(dāng)選擇結(jié)束點擊完成時候荔燎,執(zhí)行Blcok 將選中的圖片數(shù)組傳遞到首頁耻姥。

-(void)clickBtn:(UIButton *)sender{
    if (self.selectImageArray.count > 0) {
        if (self.block) {   
           // [self.navigationController popViewControllerAnimated:YES];
            self.block(self.selectImageArray);
        }
    }else {
        NSLog(@"還沒選擇圖片");
    }
}

預(yù)覽界面就不在過多敘述了,非常簡單有咨,詳情看Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蒸健,一起剝皮案震驚了整個濱河市座享,隨后出現(xiàn)的幾起案子婉商,更是在濱河造成了極大的恐慌,老刑警劉巖渣叛,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丈秩,死亡現(xiàn)場離奇詭異,居然都是意外死亡淳衙,警方通過查閱死者的電腦和手機蘑秽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來箫攀,“玉大人肠牲,你說我怎么就攤上這事⊙ヵ耍” “怎么了缀雳?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梢睛。 經(jīng)常有香客問我肥印,道長,這世上最難降的妖魔是什么绝葡? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任深碱,我火速辦了婚禮,結(jié)果婚禮上藏畅,老公的妹妹穿的比我還像新娘敷硅。我一直安慰自己,他們只是感情好墓赴,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布竞膳。 她就那樣靜靜地躺著,像睡著了一般诫硕。 火紅的嫁衣襯著肌膚如雪坦辟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天章办,我揣著相機與錄音锉走,去河邊找鬼。 笑死藕届,一個胖子當(dāng)著我的面吹牛挪蹭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播休偶,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼梁厉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起词顾,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤八秃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肉盹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昔驱,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年上忍,在試婚紗的時候發(fā)現(xiàn)自己被綠了骤肛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡窍蓝,死狀恐怖腋颠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情它抱,我是刑警寧澤秕豫,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站观蓄,受9級特大地震影響混移,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侮穿,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一歌径、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亲茅,春花似錦回铛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至袭祟,卻和暖如春验残,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巾乳。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工您没, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胆绊。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓氨鹏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親压状。 傳聞我的和親對象是個殘疾皇子仆抵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容