1. 閑談
iOS8 以后蘋果推出新的關(guān)于相冊的框架-PhotoKit,相比較之前的AssetsLibrary 框架有了很大的提升转质,由于初次接觸這個新的框架后裸,也在網(wǎng)上查找了很多大神的博客資料咳榜,本文就淺談一下自己對這個框架的理解做裙。
2.介紹
PhotoKit
主要有PHAsset
习瑰、PHFetchOptions
者娱、PHFetchResult
抡笼、PHAssetCollection
、PHImageManager
黄鳍、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。