iOS開發之擷取系統相簿中的圖片與視頻(內帶url轉換)
@話不多說,直接上代碼
#import // 必須匯入// 照片原圖路徑#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, BOOL *stop) { if (group != nil) { [weakSelf.groupArrays addObject:group]; } else { [weakSelf.groupArrays enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [obj enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *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]; [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 const *cvideoPath = [videoPath UTF8String]; FILE *file = fopen(cvideoPath, a+); if (file) { const int bufferSize = 1024 * 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]; } });}