I am building an app with button that make screen shot. Now I want to save all screen shots made in this app, in same custom name app album. I already know how to create album just the first time that app opens with code bellow.
I am creating my album with Photos framework like:
-(void)createAppAlbum
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:#"App Album Name"];
albumPlaceholder = changeRequest.placeholderForCreatedAssetCollection;
}
completionHandler:^(BOOL success, NSError *error) {
if (success) {
fetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[albumPlaceholder.localIdentifier] options:nil];
assetCollection = fetchResult.firstObject;
}
else {
NSLog(#"Error creating album: %#", error);}
}];
}
So my app creates album named "App Album Name".
I am able to take and store my screenshot in my new album with button like:
-(IBAction)screenshot:(id)sender
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[assetCollectionChangeRequest addAssets:#[[assetChangeRequest placeholderForCreatedAsset]]];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(#"Error creating asset: %#", error);
}
}];
}
In case I leave this viewController, and get back in later, I want to find album that I already created, and save another screen shot in same album, because I don't want to create new one every time I enter this view controller.
So my question is, how would I get album I created first time by Name and then save new screen shots in.
Since this question is specifically targeting, iOS 8, this code will work just fine:
- (void)saveImage:(UIImage *)image {
if (!self.library) {
self.library = [[ALAssetsLibrary alloc] init];
}
__weak ALAssetsLibrary *lib = self.library;
[self.library addAssetsGroupAlbumWithName:#"My Photo Album" resultBlock:^(ALAssetsGroup *group) {
///checks if group previously created
if(group == nil){
//enumerate albums
[lib enumerateGroupsWithTypes:ALAssetsGroupAlbum
usingBlock:^(ALAssetsGroup *g, BOOL *stop)
{
//if the album is equal to our album
if ([[g valueForProperty:ALAssetsGroupPropertyName] isEqualToString:#"My Photo Album"]) {
//save image
[lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
//then get the image asseturl
[lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
//put it into our album
[g addAsset:asset];
} failureBlock:^(NSError *error) {
}];
}];
}
}failureBlock:^(NSError *error){
}];
}else{
// save image directly to library
[lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
[lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
[group addAsset:asset];
} failureBlock:^(NSError *error) {
}];
}];
}
} failureBlock:^(NSError *error) {
}];
}
To test that this works, I created a single screen application, added a button to the view, and added a method that takes a screenshot and then passes the image to the saveImage: function. Here's the code that I added to it to make it work:
#import <AssetsLibrary/AssetsLibrary.h>
#interface ViewController ()
#property (nonatomic, strong) UIButton *screenshotButton;
#property (nonatomic, strong) ALAssetsLibrary *library;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.screenshotButton];
}
- (UIButton *)screenshotButton {
if (!_screenshotButton) {
_screenshotButton = [[UIButton alloc] initWithFrame:CGRectInset(self.view.bounds, 100.0f, 120.0f)];
_screenshotButton.layer.borderColor = [UIColor blueColor].CGColor;
_screenshotButton.layer.borderWidth = 2.0f;
_screenshotButton.layer.cornerRadius = 5.0f;
[_screenshotButton setTitle:#"Take Screenshot" forState:UIControlStateNormal];
[_screenshotButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_screenshotButton addTarget:self action:#selector(takeScreenshot) forControlEvents:UIControlEventTouchUpInside];
}
return _screenshotButton;
}
- (void)takeScreenshot {
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * imgData = UIImagePNGRepresentation(image);
if(imgData)
[imgData writeToFile:#"screenshot.png" atomically:YES];
else
NSLog(#"error while taking screenshot");
UIColor *randomColor = [UIColor colorWithHue:((CGFloat)(arc4random()%255)/255.0f)
saturation:((CGFloat)(arc4random()%255)/200.0f)
brightness:((CGFloat)(arc4random()%100)/255.0f) + 0.5f
alpha:1.0f];
self.screenshotButton.layer.borderColor = randomColor.CGColor;
[self.screenshotButton setTitleColor:randomColor forState:UIControlStateNormal];
[self saveImage:image];
}
A few things to note:
AssetsLibrary is deprecated in iOS 9, so it is not recommended to
be used after iOS 8, but will still work.
This can be implemented and
used with any UIImage passed to saveImage:, so it can work even
if you're using another library.
Make sure to include #import <AssetsLibrary/AssetsLibrary.h>.
Change "My Photo Album" to the correct album name, and possibly set that statically
Related
I need to save multiple images in the photo library, the user can multiple selects the images from the app gallery then can save them in iPhone Photo Gallery. I am showing the UIActivityViewController for the purpose.
Suppose a user selects 10 or more images and choose to save them into photo library then only 7-8 images are saved.
Is there any way by which i can save array of images in the photo library without any failure ?
Thanks
let images = Generic.fetchImagesFromMediaFiles(self.selectedMediaObj) // to fetch selected images
let activityViewController = UIActivityViewController(activityItems: images, applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil);
if let popoverPresentationController = activityViewController.popoverPresentationController {
popoverPresentationController.sourceView = self.shareAllView
}
iOS system write photo save to album use single thread, one by one to do.
if you want to save more photos same time, it maybe loss some data.
-(void)saveBtn
{
[SSGOTools againRequestPhotoWithblock:^(BOOL isAgree) {
if (isAgree) {
self.listOfImages = [NSMutableArray new];
int photoNum ;
photoNum = (int)_photoArray.count;
if (_photoArray.count > 9) {
photoNum = 9;
}
for (int i = 0; i < photoNum; i++) {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:_photoArray[i]]];
UIImage *myImage = [UIImage imageWithData:data];
//[self.listOfImages addObject:myImage];
[self loadImageFinished:myImage];
}
}
}];
}
- (void)loadImageFinished:(UIImage *)image
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//write photo save to album
[PHAssetChangeRequest creationRequestForAssetFromImage:image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
NSLog(#"success = %d, error = %#", success, error);
if(success){
dispatch_async(dispatch_get_main_queue(), ^{
[SSGOTools showInfoPopHint:#"Success"];
});
}
}];
}
you will need to use the completion block here for ensuring all images are saved.. try this :
-(void)saveBtn{
[SSGOTools againRequestPhotoWithblock:^(BOOL isAgree) {
if (isAgree) {
self.listOfImages = [NSMutableArray new];
int photoNum ;
photoNum = (int)_photoArray.count;
if (_photoArray.count > 9) {
photoNum = 9;
}
for (int i = 0; i < photoNum; i++) {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:_photoArray[i]]];
UIImage *myImage = [UIImage imageWithData:data];
[self.listOfImages addObject:myImage];
// [self loadImageFinished:myImage];
}
[self saveAllImages:self.listOfImages];
}
}];
}
-(void)saveAllImages:(NSMutableArray *)images {
UIImage *image = [images firstObject];
[images removeObject:image];
[self loadImageFinished:image :^(bool success) {
if (success){
if (images.count > 0){
[self saveAllImages:images];
}else{
// all images saved do whatever you want;
}
}else{
NSLog(#"failed saving image");
}
}];
}
- (void)loadImageFinished:(UIImage *)image :(void(^)(bool success))completion{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//write photo save to album
[PHAssetChangeRequest creationRequestForAssetFromImage:image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
NSLog(#"success = %d, error = %#", success, error);
if(success){
dispatch_async(dispatch_get_main_queue(), ^{
[SSGOTools showInfoPopHint:#"Success"];
});
}
completion(success);
}];
}
Usually when i want to read some image metadata in iOS i use imagePickerController to choose the image and Photos Framework and imagePickerController:didFinishPickingMediaWithInfo:
to get image info and extract the metadata like this
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypePhotoLibrary)
{
NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithALAssetURLs:#[url,] options:nil];
PHAsset *asset = fetchResult.firstObject;
[self metaDataFromPhotoLibrary:asset];
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
-(void)metaDataFromPhotoLibrary:(PHAsset*)asset{
// NSLog(#"Start metadata");
PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];
options.networkAccessAllowed = YES; //download asset metadata from iCloud if needed
[asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
CIImage *fullImage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];
NSDictionary *metadata = fullImage.properties;
NSMutableDictionary *imageMetadata = nil;
imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:metadata];
NSString *dateString = metadata [#"{TIFF}"] [#"DateTime"];
NSString *latitude = metadata [#"{GPS}"][#"Latitude"];
NSString *longitude = metadata [#"{GPS}"][#"Longitude"];
//etc etc etc
}
But can't do the same thing from an Action Extension
in the extension code i use a code like this to get the selected image
- (void)viewDidLoad {
[super viewDidLoad];
// Get the item[s] we're handling from the extension context.
// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
BOOL imageFound = NO;
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
// This is an image. We'll load it, then place it in our image view.
__weak UIImageView *immagine = self.immagine;
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
if(image) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[immagine setImage:image];
}];
}
}];
imageFound = YES;
break;
}
}
if (imageFound) {
// We only handle one image, so stop looking for more.
break;
}
}
}
Using UIImagePNGRepresentation or UIImageJPEGRepresentation i lost many metadata and i can read only a few data !
How can i get all image metadata from the image selected from action Extension ?
Thank you so mush
Note: i 've found some app in the AppsStore that read all metadata dictionary from extension , so there must be a solution for my problem !
Thank you again
Vanni
I am trying to get the name of the image which I have just captured from camera with following code. But [info objectForKey:#"UIImagePickerControllerReferenceURL"] always returning nil. How can I get the URL?
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.myinfo = info;
NSLog(#"Dismissing camera ui...");
[self.cameraUI dismissViewControllerAnimated:YES completion:nil];
NSLog(#"Getting media url...");
NSString *mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSLog(#"Media url = %#", mediaURL);
NSLog(#"Getting media type...");
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
NSLog(#"Selected mediaType: %#", mediaType);
if(mediaURL) {
NSLog(#"This is a video = %#", mediaURL);
if (![mediaType isEqualToString:(NSString*)kUTTypeVideo]) {
UISaveVideoAtPathToSavedPhotosAlbum(mediaURL, self, #selector(video:didFinishSavingWithError:contextInfo:), NULL);
}
} else {
NSLog(#"This is a photo...");
self.originalImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
if (self.source == UIImagePickerControllerSourceTypeCamera && [mediaType isEqualToString:(NSString*)kUTTypeImage]) {
// Image captured from camera
NSLog(#"Saving new image...");
if (self.source != UIImagePickerControllerSourceTypePhotoLibrary) {
UIImageWriteToSavedPhotosAlbum(self.originalImage, self,
#selector(image:didFinishSavingWithError:usingContextInfo:), nil);
}
}
// Image selected from previous images.
else {
NSLog(#"Getting reference url...");
self.referenceURL = [info objectForKey:#"UIImagePickerControllerReferenceURL"];
NSLog(#"Reference url = %#", [self.referenceURL absoluteString]);
[self saveAssetData:self.originalImage :info];
}
}
}
- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
usingContextInfo:(void*)ctxInfo {
if (error) {
NSLog(#"Resim kaydedilemedi: %#", [error localizedDescription]);
NSString *title = #"Resim kaydedilemedi!";
NSString* message = #"Resim kaydedilirken hata oluştu!";
[self alertStatus:message:title];
} else {
NSLog(#"Save asset data...");
[self saveAssetData:image :self.myinfo];
}
}
- (void)saveAssetData:(UIImage*)originalImage :(NSDictionary*)info {
self.assetLibrary = [[ALAssetsLibrary alloc] init];
NSURL *url = [info objectForKey:#"UIImagePickerControllerReferenceURL"];
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset)
{
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
NSString *filename = [assetRep filename];
NSLog(#"File name = %#", filename);
if(self.selectedMediaNames == nil)
self.selectedMediaNames = [[NSMutableArray alloc] init];
[self.selectedMediaNames addObject:filename];
[self.tableView reloadData];
[self.activitIndicator stopAnimating];
[self.activitIndicator setHidden:true];
HMXSharedDataManager *sharedDataManager =
[HMXSharedDataManager sharedManager];
[sharedDataManager.uploaMedias addObject:originalImage];
[sharedDataManager.uploaMediaNames addObject:filename];
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *error)
{
NSLog(#"%#", error);
};
[self.assetLibrary assetForURL:url resultBlock:resultblock failureBlock:failureblock];
}
UPDATE:
It is a little bit late but here how I get the name of the image or video:
Check UIImagePickerControllerMediaURL, if it is null the media is an image if not it is a video
If the image or the video is just taken or recorded save it to photos album
Use ALAssetsLibrary to query file name.
Here is the code for saving and getting media:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
#try {
[self.cameraUI dismissViewControllerAnimated:YES completion:nil];
mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];
// If mediaURL is not null this should be a video
if(mediaURL) {
// This video is new just recorded with camera
if (self.source == UIImagePickerControllerSourceTypeCamera) {
// First save the video to photos album
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library writeVideoAtPathToSavedPhotosAlbum:mediaURL completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
DDLogDebug(#"Failed to save the photo to photos album...");
} else {
// Get the name of the video
[self getMediaName:nil url:assetURL];
}
}];
} else { // This is a video that recorded before
// Get the name of the video
[self getMediaName:nil url:[info objectForKey:UIImagePickerControllerReferenceURL]];
}
}
// This is an image
else {
self.originalImage = (UIImage*)[info objectForKey:UIImagePickerControllerOriginalImage];
// This image is new just taken with camera
if (self.source == UIImagePickerControllerSourceTypeCamera) {
// First save the image to photos album
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library writeImageToSavedPhotosAlbum:[self.originalImage CGImage]
orientation:(ALAssetOrientation)[self.originalImage imageOrientation]
completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
DDLogDebug(#"Failed to save the vide to photos album...");
} else {
// Get the name of the image
[self getMediaName:self.originalImage url:assetURL];
}
}];
} else { // This is an image that taken before
// Get the name of the image
[self getMediaName:self.originalImage
url:[info objectForKey:#"UIImagePickerControllerReferenceURL"]];
}
}
}
#catch (NSException *exception) {
DDLogError(#"%#", [exception description]);
}
}
Actual method that gets the media name:
- (void)getMediaName:(UIImage*)originalImage url:(NSURL*)url {
#try {
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset) {
if (asset == nil) return;
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
NSString *fileName = [assetRep filename];
// Do what you need with the file name here
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *error) {
DDLogError(#"Failed to get image or video name : %#", error);
};
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library assetForURL:url resultBlock:resultblock failureBlock:failureblock];
}
#catch (NSException *exception) {
DDLogError(#"%#", [exception description]);
}
}
The image that you capture with the camera from within the application has no name. It is always nil. You have to programmatically save that image in the photo gallery and you can save with any name you want.
Put the following code in didFinishPickingMediaWithInfo:
NSURL *mediaUrl;
NSString *imageURLString;
self.selectImage = [info valueForKey:UIImagePickerControllerEditedImage];
if (mediaUrl == nil) {
if (self.selectImage == nil) {
self.selectImage = [info valueForKey:UIImagePickerControllerOriginalImage];
DebugLog(#"Original image picked.");
}else {
DebugLog(#"Edited image picked.");
}
}
mediaUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL];
imageURLString=[mediaUrl absoluteString];
DebugLog(#"Hi Image URL STRING : - %#",imageURLString);
if ([StringUtils string:imageURLString contains:#"PNG"] || [StringUtils string:imageURLString contains:#"png"]) {
self.isJPG = NO;
self.profileImageName = #"profileImageName.png";
} else if ([StringUtils string:imageURLString contains:#"JPG"] || [StringUtils string:imageURLString contains:#"jpg"]) {
self.isJPG = YES;
self.profileImageName = #"profileImageName.jpg";
}
When you set camera for kUTTypeMovie , then only you will get referenceurl and mediaurl. It will return null for kUTTypeImage.
For Xamarin.iOS developers: store image capture from camera and get its data using ALAssetsLibrary
var originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
var meta = e.Info[UIImagePickerController.MediaMetadata] as NSDictionary;
//Get image bytes
if (originalImage != null)
{
using (NSData imageData = originalImage.AsPNG())
{
myByteArray = new Byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, myByteArray, 0, Convert.ToInt32(imageData.Length));
}
//This bit of code saves image to the Photo Album with metadata
ALAssetsLibrary library = new ALAssetsLibrary();
library.WriteImageToSavedPhotosAlbum(originalImage.CGImage, meta, (assetUrl, error) =>
{
library.AssetForUrl(assetUrl, delegate (ALAsset asset)
{
ALAssetRepresentation representation = asset.DefaultRepresentation;
if (representation != null)
{
string fileName = representation.Filename;
var filePath = assetUrl.ToString();
var extension = filePath.Split('.')[1].ToLower();
var mimeData = string.Format("image/{0}", extension);
var mimeType = mimeData.Split('?')[0].ToLower();
var documentName = assetUrl.Path.ToString().Split('/')[1];
}
}, delegate (NSError err) {
Console.WriteLine("User denied access to photo Library... {0}", err);
});
});
}
So I'm building an app that the user takes pictures of themselves, it saves them to the camera roll, and I'm saving references to the asset URLs to display them in the app. At first this model seemed to work fine, but as I took more and more pictures it started receiving memory warnings and eventually crashed. Is there a better way to approach this?
This is how I load up the saved photos at the launch of the app (which freezes the app for up to 10 seconds depending on how many are being loaded):
- (void) loadPhotosArray
{
_photos = [[NSMutableArray alloc] init];
NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey: #"savedImages"];
if (data)
{
NSArray* storedUrls = [[NSArray alloc] initWithArray: [NSKeyedUnarchiver unarchiveObjectWithData: data]];
// reverse array
NSArray* urls = [[storedUrls reverseObjectEnumerator] allObjects];
for (NSURL* assetUrl in urls)
{
// Block to handle image handling success
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref) {
UIImage* tempImage = [UIImage imageWithCGImage:iref];
UIImage* image = [[UIImage alloc] initWithCGImage: tempImage.CGImage scale: 1.0 orientation: UIImageOrientationRight];
// Set image in imageView
[_photos addObject: image];
[[NSNotificationCenter defaultCenter] postNotificationName: #"PhotosChanged" object: self];
}
};
// Handles failure of getting image
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(#"Can't get image - %#",[myerror localizedDescription]);
};
// Load image then call appropriate block
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL: assetUrl
resultBlock: resultblock
failureBlock: failureblock];
}
}
else
{
NSLog(#"Photo storage is empty");
}
}
And saving photos:
- (void) addImageToPhotos: (UIImage*)image
{
// Store image at front of array
NSMutableArray* temp = [[NSMutableArray alloc] initWithObjects: image, nil];
// load rest of images onto temp array
for (UIImage* image in _photos)
{
[temp addObject: image];
}
_photos = nil;
_photos = [[NSMutableArray alloc] initWithArray: temp];
// [self.photos addObject: image];
[[NSNotificationCenter defaultCenter] postNotificationName: #"PhotosChanged" object: self.photos];
// save to cache
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library saveImage: image toAlbum: #kAlbumeName withCompletionBlock:^(NSError *error) {
if (error)
{
NSLog(#"Error saving");
}
}];
}
I think have 2 methods to optimize this problem.
U should just save image name string instead of saving UIImage object, then when need to display the image, use pagination to display image according to saved image name string.
U should use multi-thread to deal with this long time task, recommend u to use gcd to load image name string.
We try asynchronously load images from photo album to different UIImageView. But now, after big delay all images load together.
- (void)loadAllAssetWithHandler:(void (^)(ALAsset *))hanlderAssetDidLoad
{
ALAssetsLibraryAccessFailureBlock blockFailure = ^(NSError *error){
NSLog(#"ERROR = %#", error.description);
};
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
if (group == nil) {
return;
}
if([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString: #"album"])
{
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if(asset == nil) {
return;
}
hanlderAssetLoad(asset);
}];
return;
}
};
// Enumerate Albums
[library enumerateGroupsWithTypes: ALAssetsGroupAll
usingBlock: assetGroupEnumerator
failureBlock: blockFailure];
[library release];
}
And
[self loadAllAssetsWithHandlert:^(ALAsset *asset) {
UIImageView *imageView = [self nextImageVIew];
imageView.image = [UIImage imageWithCGImage: asset.defaultRepresentation.fullResolutionImage]; //or thumbnail
}];
So, how do we make pictures uploaded to the UIImageView by turns (immediately after each upload) ?