好些天沒寫點東西了,最近公司要做新項目,有點小忙。不想我的堅持就此中綴,我把我前些天研討的東西拿出來給大家看看。
這次整理的是AssetsLibrary和PhotoKit的運用。自己處女座,有點強迫症,之前寫的項目裡用的是AssetsLibrary寫的調取相冊內的媒體文件,但是Xcode總是報正告錯誤,雖然可以編譯並展現效果,但是十幾個正告錯誤掛在那,心裡總不是味道,所以我就研討了一下AssetLibrary和PhotoKit。
在 IOS 8 呈現之前,開發者只能運用 AssetsLibrary 框架來訪問設備的照片庫,這是一個有點跟不上 IOS 使用開展步伐以及代碼設計准繩但的確弱小的框架,思索到 IOS7 仍占有不少的浸透率,因而 AssetsLibrary 也是本文重點引見的局部。而在 iOS8 呈現之後,蘋果提供了一個名為 PhotoKit 的框架,一個可以讓使用更好地與設備照片庫對接的框架。
一、AssetsLibrary 組成
AssetsLibrary 的組成比擬契合照片庫自身的組成,照片庫中的完好照片庫對象、相冊、相片都能在 AssetsLibrary 中找到逐個對應的組成,這使到 AssetsLibrary 的運用變得直觀而方便。想要理解AssetsLibrary得從它的類開端。
AssetsLibrary: 代表整個設備中的資源庫(照片庫),經過 AssetsLibrary 可以獲取和包括設備中的照片和視頻
ALAssetsGroup: 映射照片庫中的一個相冊,經過 ALAssetsGroup 可以獲取某個相冊的信息,相 冊下的資源,同時也可以對某個相冊添加資源。 ALAsset: 映射照片庫中的一個照片或視頻,經過 ALAsset 可以獲取某個照片或視頻的詳細信息, 或許保管照片和視頻。 ALAssetRepresentation: ALAssetRepresentation 是對 ALAsset 的封裝(但不是其子類),可以更方便地獲取 ALAsset 中的資源信息,每個 ALAsset 都有至多有一個 ALAssetRepresentation 對象,可以經過 defaultRepresentation 獲取。而例如運用零碎相機使用拍攝的 RAW + JPEG 照片,則會有兩個 ALAssetRepresentation,一個封裝了照片的 RAW 信息,另一個則封裝了照片的 JPEG 信息。@話不多說,直接上代碼
#import <AssetsLibrary/AssetsLibrary.h> // 必需導入 // 照片原圖途徑 #define KOriginalPhotoImagePath \ [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"OriginalPhotoImages"] // 視頻URL途徑 #define KVideoUrlPath \ [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"VideoURL"] // caches途徑 #define KCachesPath \ [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] // MainViewController @interface MTHMainViewController () @property (nonatomic,strong) MTHNextViewController *nextVC; @property (nonatomic,strong) NSMutableArray *groupArrays; @property (nonatomic,strong) UIImageView *litimgView; @end @implementation MTHMainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"Demo"; self.view.backgroundColor = [UIColor clearColor]; // 初始化 self.groupArrays = [NSMutableArray array]; // 測試BarItem self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"測試" style:UIBarButtonItemStylePlain target:self action:@selector(testRun)]; // 測試手勢 UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithtarget:self action:@selector(didClickPanGestureRecognizer:)]; [self.navigationController.view addGestureRecognizer:panRecognizer]; // 圖片或許視頻的縮略圖顯示 self.litimgView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 200, 120, 120)]; [self.view addSubview:_litimgView]; } - (void)testRun { __weak MTHMainViewController *weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOLBOOL *stop) { if (group != nil) { [weakSelf.groupArrays addObject:group]; } else { [weakSelf.groupArrays enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOLBOOL *stop) { [obj enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOLBOOL *stop) { if ([result thumbnail] != nil) { // 照片 if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]){ NSDate *date= [result valueForProperty:ALAssetPropertyDate]; UIImage *image = [UIImage imageWithCGImage:[result thumbnail]]; NSString *fileName = [[result defaultRepresentation] filename]; NSURL *url = [[result defaultRepresentation] url]; int64_t fileSize = [[result defaultRepresentation] size]; NSLog(@"date = %@",date); NSLog(@"fileName = %@",fileName); NSLog(@"url = %@",url); NSLog(@"fileSize = %lld",fileSize); // UI的更新記得放在主線程,要不然等子線程排隊過去都不知道什麼年代了,會很慢的 dispatch_async(dispatch_get_main_queue(), ^{ self.litimgView.image = image; }); } // 視頻 else if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo] ){ // 和圖片辦法相似 } } }]; }]; } }; ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) { NSString *errorMessage = nil; switch ([error code]) { case ALAssetsLibraryAccessUserDeniedError: case ALAssetsLibraryAccessGloballyDeniedError: errorMessage = @"用戶回絕訪問相冊,請在<隱私>中開啟"; break; default: errorMessage = @"Reason unknown."; break; } dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"錯誤,無法訪問!" message:errorMessage delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil nil]; [alertView show]; }); }; ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:listGroupBlock failureBlock:failureBlock]; }); }
@但是:
依照下面辦法直接取出來的途徑是無法傳輸的,必需自己轉化成NSData對象重新寫入沙盒途徑
// 將原始圖片的URL轉化為NSData數據,寫入沙盒 - (void)imageWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // 進這個辦法的時分也應該加判別,假如曾經轉化了的就不要調用這個辦法了 // 如何判別曾經轉化了,經過能否存在文件途徑 ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; // 創立寄存原始圖的文件夾--->OriginalPhotoImages NSFileManager * fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:KOriginalPhotoImagePath]) { [fileManager createDirectoryAtPath:KOriginalPhotoImagePath withIntermediateDirectories:YES attributes:nil error:nil]; } dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (url) { // 次要辦法 [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) { ALAssetRepresentation *rep = [asset defaultRepresentation]; Byte *buffer = (Byte*)malloc((unsigned long)rep.size); NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:((unsigned long)rep.size) error:nil]; NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; NSString * imagePath = [KOriginalPhotoImagePath stringByAppendingPathComponent:fileName]; [data writeToFile:imagePath atomically:YES]; } failureBlock:nil]; } }); } // 將原始視頻的URL轉化為NSData數據,寫入沙盒 - (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // 解析一下,為什麼視頻不像圖片一樣一次性開拓自身大小的內存寫入? // 想想,假如1個視頻有1G多,難道直接開拓1G多的空間大小來寫? ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (url) { [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) { ALAssetRepresentation *rep = [asset defaultRepresentation]; NSString * videoPath = [KCachesPath stringByAppendingPathComponent:fileName]; char constconst *cvideoPath = [videoPath UTF8String]; FILEFILE *file = fopen(cvideoPath, "a+"); if (file) { const int bufferSize = 11024 * 1024; // 初始化一個1M的buffer Byte *buffer = (Byte*)malloc(bufferSize); NSUInteger read = 0, offset = 0, written = 0; NSError* err = nil; if (rep.size != 0) { do { read = [rep getBytes:buffer fromOffset:offset length:bufferSize error:&err]; written = fwrite(buffer, sizeof(char), read, file); offset += read; } while (read != 0 && !err);//沒到開頭,沒出錯,ok持續 } // 釋放緩沖區,封閉文件 free(buffer); buffer = NULL; fclose(file); file = NULL; } } failureBlock:nil]; } }); }
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持本站。
【iOS開發之獲取零碎相冊中的圖片與視頻教程(內帶url轉換)】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!