1. 閑談
iOS8 以后蘋果推出新的關于相冊的框架-PhotoKit,相比較之前的AssetsLibrary 框架有了很大的提升,由于初次接觸這個新的框架,也在網上查找了很多大神的博客資料,本文就淺談一下自己對這個框架的理解。
2.介紹
PhotoKit
主要有PHAsset
、PHFetchOptions
、PHFetchResult
、PHAssetCollection
、PHImageManager
、PHCollectionList
幾個重要的類。
PHAsset
:代表照片庫的一個資源 也就是具體的某一個照片或者視頻。
PHFetchOptions
: 獲取資源的參數 可以為nil
PHFetchResult
:表示一系列的資源結果集合,也可以是相冊的集合 從PHCollection
的方法中獲得.
PHAssetCollection
: PHCollection
的子類,表示一個相冊或者一個時刻(最近刪除、收藏)
PHImageManager
:用于處理資源的加載,加載圖片的過程有緩存,可以使用 PHImageRequestOptions
控制資源的輸出尺寸等規格
PHCollectionList
:表示一組PHCollection
3.開始搭建
- 3.1 由于從相冊獲取照片之后需要展示,所有首先我們需要創建一個展示你選中照片的界面,因此我使用的是
UICollectionView
布局界面,并自定義了一個UICollectionViewCell
可以實現刪除照片 命名為 -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 創建一個管理獲取相冊資源的工具類 -
YHPhotosData
,使用這個工具類實現以下功能:獲取所有相冊列表、獲取某一個相冊中的照片資源、 將具體某一個照片資源轉化為照片。
YHPhotosData.h
文件中
#import <Foundation/Foundation.h>
#import <Photos/Photos.h>//系統照片的框架
@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列出所有的用戶創建的相冊
PHFetchResult *userResult = [PHAssetCollection fetchTopLevelUserCollectionsWithOptions:nil];
for (PHAssetCollection *sub in userResult) {
[dataArray addObject:sub];
}
return dataArray;
}
+(NSMutableArray *)getPhotosForPHAssetCollection:(PHAssetCollection *)collection{
NSMutableArray *photosArray = [NSMutableArray array];
//1.獲取了結果集
PHFetchResult *photosResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
//2.便利結果集 取出具體某一張圖片資源 添加在數組中
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根據圖片自身比例計算照片在屏幕上的高
CGFloat pixheight = mainWidth/setScale;
/**
* PHImageManager 是通過請求的方式拉取圖像,并可以控制請求得到的圖像的尺寸、剪裁方式、質量,緩存以及請求本身的管理(發出請求、取消請求)等
*
* @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) {
// 排除取消,錯誤,低清圖三種情況,即已經獲取到了高清圖
BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
if (downloadFinined) {
//回調
if (complection){
complection(result,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
}
}
}];
}
}
- 3.3 工具類寫完之后,接下來開始創建相冊列表控制器
PhotosListVC
用來展示所有的相冊列表,同時自定義Cell(我這里定義的是PhotoListCell
)用來顯示每個相冊。cell中顯示的照片就是該相冊中所有照片中的最后一張。
PhotoListCell
定義非常簡單,我在這里就不過多敘述了.
/**圖片視圖*/
@property(nonatomic,strong)UIImageView *photoView;
/**標題*/
@property(nonatomic,strong)UILabel *title;
這里比較重要的一個方法就是 給cell設置默認數據。既相冊的標題 以及顯示的照片(最后一張).
///設置數據
-(void)getImageForAssetCollection:(PHAssetCollection *)coll{
//獲取該相冊最后一張照片資源
PHAsset *set = [[YHPhotosData getPhotosForPHAssetCollection:coll] lastObject] ;
//轉化為照片 并設置數據 (由于相冊可能沒有照片需要判斷一下,給一張默認的照片)
[[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 創建展示相冊所有照片的控制器
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;
//設置數據
-(void)setPhotoForPHAsset:(PHAsset *)set;
@end
PhotosShowCell.m
中
//設置cell數據 傳遞過來的都是一張照片資源 不是照片 需要轉化
-(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) {
// 排除取消,錯誤,低清圖三種情況,即已經獲取到了高清圖
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
創建一個可變數組selectImageArray
存放選中的所有照片,在cell的點擊方法中 執行cell的block方法獲取到點擊的照片, 并存放到數組selectImageArray
中,同時改變cell上按鈕的狀態。
-(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
創建完成、預覽按鈕以及定義一個返回首頁并傳遞照片到首頁的Blcok ,當選擇結束點擊完成時候,執行Blcok 將選中的圖片數組傳遞到首頁。
-(void)clickBtn:(UIButton *)sender{
if (self.selectImageArray.count > 0) {
if (self.block) {
// [self.navigationController popViewControllerAnimated:YES];
self.block(self.selectImageArray);
}
}else {
NSLog(@"還沒選擇圖片");
}
}
預覽界面就不在過多敘述了,非常簡單,詳情看Demo。