#import <AssetsLibrary/AssetsLibrary.h> // must be imported // original image path #define KOriginalPhotoImagePath [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"OriginalPhotoImages"] // video URL path #define KVideoUrlPath [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"VideoURL"] // caches path #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]; // initialize self.groupArrays = [NSMutableArray array]; // test BarItem self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"测试" style:UIBarButtonItemStylePlain target:self action:@selector(testRun)]; // test gesture UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didClickPanGestureRecognizer:)]; [self.navigationController.view addGestureRecognizer:panRecognizer]; // Thumbnail display of image or video 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) { // Photo 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); // Remember to put the UI update on the main thread, otherwise it will be very slow if you wait for the sub-threads to queue up and you won't know the age. dispatch_async(dispatch_get_main_queue(), ^{ self.litimgView.image = image; }); } // video else if ([[result valueForProperty: ALAssetPropertyType] isEqualToString: ALAssetTypeVideo]) { // Similar to the image method } } }]; }]; } }; ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) { NSString *errorMessage = nil; switch ([error code]) { case ALAssetsLibraryAccessUserDeniedError: case ALAssetsLibraryAccessGloballyDeniedError: errorMessage = @"The user refuses to access the album, please enable it in <Privacy>"; break; default: errorMessage = @"Reason unknown."; break; } dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Error, cannot access!" message:errorMessage delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; [alertView show]; }); }; ALAssetsLibrary * assetsLibrary = [[ALAssetsLibrary alloc] init]; [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:listGroupBlock failureBlock:failureBlock]; }); }
The path directly taken out according to the above method cannot be transmitted, and must be converted into an NSData object and re-written to the sandbox path
// Convert the URL of the original image into NSData data and write it into the sandbox - (void)imageWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // You should also add judgment when entering this method. If it has been converted, don't call this method. // How to judge that it has been converted, by whether there is a file path ALAssetsLibrary * assetLibrary = [[ALAssetsLibrary alloc] init]; // Create a folder to store the original images--->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) { // main method [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]; } }); } // Convert the URL of the original video into NSData data and write it into the sandbox - (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName { // Analyze, why does the video not open up its own size of memory to write at one time like the picture? // Think about it, if a video has more than 1G, is it possible to directly open up more than 1G of space to write? 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; // Initialize a 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);//No end, no error, ok continue } // free the buffer, close the file free(buffer); buffer = NULL; fclose(file); file = NULL; } } failureBlock:nil]; } }); }