iOS開發------簡單實現圖片多選功能(AssetsLibrary篇)

來源:互聯網
上載者:User

iOS開發------簡單實現圖片多選功能(AssetsLibrary篇)

AssetsLibrary.framework是iOS7.0之前用來擷取手機所有的媒體資源的一個靜態庫,在iOS8.0之後完全可以用Photo.framework來代替,但因為涉及到適配iOS7,所以這個庫用的還是比較多的。

實際上,多選圖片有很多很好用的第三方,但找到一個完全符合自己需求的第三方也不是那麼容易,就算找到,如果不懂,也不是很好修改代碼才對,所以瞭解一下這個庫也是很有必要的,這裡就記錄一下過程中的認識與問題。

如果小夥伴有什麼好玩的庫,還請介紹一下,很希望能和喜歡鑽研技術的你們一起交流。
下面的內容是邊看開發文檔邊研究使用,按自己的理解所寫,如果出現錯誤,也請告知一下Thanks()

本文中的所有代碼:https://github.com/YRunIntoLove/YAImagePickerView

 

類邏輯

研究一個庫或者架構,總體邏輯一定是要縷清的,下面是個人的理解:
- ALAssetsLibrary 是一個資產庫,所有的資源群組最初都是從這個類的對象中獲得.
- ALAssetsGroup 是一個資源群組,裡麵包含了每個資源群組的基本資料以及包含的所有資源,可以通過設定過濾器屬性來選擇自己想要的資源類型.
- ALAssetsFilter 是一個過濾器,比如需要從資源群組中遍曆出所有的資源,視頻資源還是圖片資源.
- ALAsset 是一個資來源物件,裡面可以取到組的資訊,詳細資料可以通過擷取自身的詳細對象來擷取
- ALAssetRepresentation 是資來源物件的詳細資料,ALAsset的詳細內容都存在這個類中,比如高清圖就存在該對象中。

 

類庫中的類及其屬性方法

這裡提到的都是代碼中用到的屬性和方法,如果只是為了多圖選擇,那麼以下的方法應該是夠用的,不夠的話可以Command+單擊進入開發文檔查看即可。
 

ALAssetsLibrary

資產庫對象:

/***相互關聯類型***/ALAssetsGroupLibrary        //從iTunes 來的相簿內容(如本身內建的向日葵照片)ALAssetsGroupAlbum          //裝置自身產生或從iTunes同步來的照片,但是不包括照片流跟分享流中的照片。(例如從各個軟體中儲存下來的圖片)ALAssetsGroupEvent          //相機介面事件產生的相簿ALAssetsGroupFaces          //臉部相簿(具體不清楚)ALAssetsGroupSavedPhotos    //"相簿菲林"裡面的照片ALAssetsGroupPhotoStream    //照片流ALAssetsGroupAll            //除了ALAssetsGroupLibrary上面所的內容
/*遍曆相互關聯類型的資源群組*/- (void)enumerateGroupsWithTypes:(ALAssetsGroupType)types                      usingBlock:(ALAssetsLibraryGroupsEnumerationResultsBlock)enumerationBlock                    failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock;

 

ALAssetsGroup

資源群組對象:

/***屬性的key***/extern NSString *const ALAssetsGroupPropertyName ;              //組的標題extern NSString *const ALAssetsGroupPropertyType;               //組的類型extern NSString *const ALAssetsGroupPropertyPersistentID ;      //組的代表IDextern NSString *const ALAssetsGroupPropertyURL;                //該組在本機存放區的位置url
//擷取相關屬性的方法,property的值從上面的屬性key中取即可- (id)valueForProperty:(NSString *)property;//擷取資源群組的預覽圖- (CGImageRef)posterImage;//設定過濾器- (void)setAssetsFilter:(ALAssetsFilter *)filter;//當前組的資源數,如果設定了過濾對象,此數目就是過濾之後儲存資來源物件的個數- (NSInteger)numberOfAssets;
/***遍曆資源的方法***///遍曆所有的資源- (void)enumerateAssetsUsingBlock:(ALAssetsGroupEnumerationResultsBlock)enumerationBlock;//根據類型遍曆- (void)enumerateAssetsWithOptions:(NSEnumerationOptions)option                        usingBlock:(ALAssetsGroupEnumerationResultsBlock)enumerationBlock;
//類型typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions) {    NSEnumerationConcurrent = (1UL << 0),  //順序(Default)    NSEnumerationReverse = (1UL << 1),     //逆序};

 

ALAssetsFilter

資源過濾器:

//獲得組中所有的照片資源+ (ALAssetsFilter *)allPhotos;//獲得組中所有的視頻資源+ (ALAssetsFilter *)allVideos;//獲得組中所有的資源+ (ALAssetsFilter *)allAssets;

 

ALAsset

資來源物件:

/***相關屬性的key***/extern NSString *const ALAssetPropertyType;             //資來源物件的類型extern NSString *const ALAssetPropertyLocation;         //資來源物件的位置描述extern NSString *const ALAssetPropertyDuration;         //資來源物件的期間(用於video類型的資來源物件)extern NSString *const ALAssetPropertyOrientation;      //資來源物件的方向,如:左轉,右轉..extern NSString *const ALAssetPropertyDate;             //資來源物件的建立時間對象extern NSString *const ALAssetPropertyRepresentations;  //資來源物件的可用詳細對象數組extern NSString *const ALAssetPropertyURLs;             //資來源物件的詳細對象的URLsextern NSString *const ALAssetPropertyAssetURL;         //資來源物件的資源標識碼/***相互關聯類型的key***/extern NSString *const ALAssetTypePhoto;            //圖片類型extern NSString *const ALAssetTypeVideo;            //視頻類型extern NSString *const ALAssetTypeUnknown;          //位置類型
//擷取相關屬性的方法,property的值從上面的屬性key中取即可,與ALAssertGroup是一樣的- (id)valueForProperty:(NSString *)property//擷取自身詳細資料對象的一個便利方法- (ALAssetRepresentation *)defaultRepresentation;//擷取一個方形的縮圖,但是不建議用,真是太模糊了- (CGImageRef)thumbnail;//擷取一個按照比例縮放的縮圖,建議用這個,還是比較清晰的(Demo中的屬性用的是這個屬性)- (CGImageRef)aspectRatioThumbnail;

 

ALAssetRepresentation

資源詳情對象:

//當前對象的方向- (ALAssetOrientation)orientation;//獲得縮放比例- (float)scale;
//獲得一個鋪滿螢幕的高清圖(Demo中預覽的高清圖就是取得這個屬性)- (CGImageRef)fullScreenImage;//如果使用這個屬性,直接用此方法產生UIImage對象UIImage * image = [UIImage imageWithCGImage:fullScreenImage];
//獲得一個重新處理的鋪滿螢幕的高清圖- (CGImageRef)fullResolutionImage;//如果使用這個屬性,需要用下面的方法產生UIImage對象,不然會出現展示方向等錯誤,比片顯示會變成左轉90度的UIImage * image = [UIImage UIImage imageWithCGImage:fullResolutionImage                                              scale:fullResolutionImage.scale                                        orientation:fullResolutionImage.orientation];

 

Demo部分代碼設定檔_YEnumConfig
////  YEnumConfig.h//  YChoosePicturesDemo////  Created by YueWen on 16/4/15.//  Copyright ? 2016年 YueWen. All rights reserved.//#ifndef YEnumConfig_h#define YEnumConfig_h@import UIKit;@import AssetsLibrary;#pragma mark - typedef enum : NSUInteger {    YChoosePhotoSequenceTypeDefault = 0,    //預設是按照選擇的順序    YChoosePhotoSequenceTypeDate            //按照圖片在相簿的順序} YChoosePhotoSequenceType;#pragma mark -//照片選擇的Block回調typedef void(^ImagesBlock)(NSArray  *);#pragma mark - YPhotoManagertypedef void(^ALAssetGroupBlock)(NSArray  * groups);typedef void(^ALAssetPhotoBlock)(NSArray  * photos);typedef void(^ALAssetFailBlock)(NSString * error);#pragma mark - YPhotoCollectionViewCelltypedef void(^YPhotoCollectionViewBlock)(void);#endif /* YEnumConfig_h */

 

圖片請求_YPhotoManager

按照習慣,還是建立了一個YPhotoManager的單例

@interface YPhotoManager ()@property (nonatomic, strong) ALAssetsLibrary * library;                    //資產庫@property (nonatomic, copy) ALAssetGroupBlock block;                        //資源群組進行的回調@property (nonatomic, strong) NSMutableArray  * groups;    //存放所有照片組的數組對象@property (nonatomic, strong) NSMutableArray  * photos;          //存放所有照片的數組對象@end
建立單獨的相簿
/** *  建立組名叫做title的相片組 * *  @param title 組名 */- (void)createGroupWithTitle:(NSString *)title{    //開始建立    [self.library addAssetsGroupAlbumWithName:title resultBlock:^(ALAssetsGroup *group) {        //coding success    } failureBlock:^(NSError *error) {        //coding error    }];}
請求所有的照片組

讀取所有的資源群組對象,其實就是枚舉遍曆,每次獲得一個group對象都會進行一次回調,同步會略微卡頓,所以使用非同步回調Block

#pragma mark - 讀取相簿的所有組/** *  讀取相簿的所有組 * *  @param groupBlock       擷取組成功的回調 *  @param failBlock        失敗的回調 *  @param cameraRollHandle 相機菲林不為nil時候進行的回調 */-(void)readAllPhotoGroups:(ALAssetGroupBlock)groupBlock Fail:(ALAssetFailBlock)failBlock CameraRollHandel:(void (^)(void))cameraRollHandle{    //刪除之前存的所有組    [self.groups removeAllObjects];    __block __weak typeof(self) copy_self = self;    //開始遍曆    [self.library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {        //如果返回的組存在        if (group)        {            //對group進行過濾,只要照片            [group setAssetsFilter:[ALAssetsFilter allPhotos]];            //添加資料            [copy_self.groups addObject:group];            //進行順序判斷,目的是將菲林相簿放到第一位            if([self containCameraRoll:group] == true)            {                //刪除當前位置的數組                [self.groups removeObjectAtIndex:self.groups.count - 1];                [self.groups insertObject:group atIndex:0];            }            //回調資料            groupBlock([NSArray arrayWithArray:copy_self.groups]);            //進行序列後的回調            if([self containCameraRoll:group] == true)                cameraRollHandle();        }    } failureBlock:^(NSError *error) {        //失敗回調        failBlock(error.localizedDescription);    }];}

這裡載入所有的組,所以相機菲林那個組位置不會是第一個,但是又想它在第一行,增加這個判斷來保證存在相機菲林,為其他動作進行準備:

/** *  判斷是否包含相機菲林 * *  @param group ALAssetsGroup對象 * *  @return true表示包含,false反之 */- (BOOL)containCameraRoll:(ALAssetsGroup *)group{    //如果是相機菲林,放到第一位,這裡只適配英文以及中文    NSString * nameCN = NSLocalizedString([group valueForProperty:ALAssetsGroupPropertyName], @"");    NSString * nameEN = NSLocalizedString([group valueForProperty:ALAssetsGroupPropertyName], @"");    //對當前組數進行排序    if ([nameCN isEqualToString:@"相機菲林"]        || [nameEN isEqualToString:@"Camera Roll"])    {        //修改變數        return true;    }    return false;}
請求組中的所有照片資源

1、要想請求組中的資源,首先要開啟這個組對象

#pragma mark - 開啟相片組-(void)openPhotosGroup:(ALAssetsGroup *)assetsGroup Success:(ALAssetPhotoBlock)successBlock Fail:(ALAssetFailBlock)failBlock{    //刪除所有的照片對象    [self.photos removeAllObjects];    //避免強引用    __block __weak typeof(self) copy_self = self;    //擷取當前組的url資料    NSURL * url = [assetsGroup valueForProperty:ALAssetsGroupPropertyURL];    //開啟當前的資源群組對象    [self.library groupForURL:url resultBlock:^(ALAssetsGroup *group) {        [copy_self photosInGroups:group Block:successBlock];    } failureBlock:^(NSError *error) {        //失敗的回調        failBlock(error.localizedDescription);    }];}

2、在開啟的組裡面進行遍曆並回調資料

//擷取所有的照片對象並回調資料- (void)photosInGroups:(ALAssetsGroup *)group Block:(ALAssetPhotoBlock)photoBlock{    //開始讀取    [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {        //如果不為空白或者媒體為圖片        if (result != nil && [[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto])        {               //添加資料            [self.photos addObject:result];            //數目達標後統一進行回調            if (index == group.numberOfAssets - 1)            {                //回調                photoBlock([NSArray arrayWithArray:self.photos]);            }        }    }];}

用到的資料基本都謝了,至於View以及ViewController因為太長,就不在這裡佔地方了,如果有想法,可以下載代碼研究一下。

最後還是要嘮叨一句,不管是UIImageView還是UIButton,顯示縮圖的時候不要忘記設定contentMode屬性,這樣才會出現選擇展示圖中的效果:

//這裡表示如果圖太大,根據高寬中的最大數值進行展示,所以會有一部分不顯示UIViewContentModeScaleAspectFill//他和上面的屬性相反,它是根據高寬終的最小數值進行展示UIViewContentModeScaleAspectFit
//如果是CollectionCell中進行展示的,設定如下Self.contentMode = UIViewContentModeScaleAspectFill;//如果是瀏覽高清圖的時候,設定如下Self.contentMode = UIViewContentModeScaleAspectFit;

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.