I am trying to go through and clean up some deprecation warnings by updating ALAsset with PHPhoto. I am getting confused by this code and need some help to make sure I am not missing something. I added in some comments about what is confusing me.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSURL *assetsURL = [info objectForKey:UIImagePickerControllerReferenceURL];
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
// This is where I am getting confused.
// What is the difference between the meta data of the else statement
// and the if statement.
if (assetsURL) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[library assetForURL:assetsURL
resultBlock:^(ALAsset *asset) {
[metadata addEntriesFromDictionary:asset.defaultRepresentation.metadata];
dispatch_semaphore_signal(sema);
}
failureBlock:^(NSError *error) {
dispatch_semaphore_signal(sema);
}];
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else {
[metadata addEntriesFromDictionary:[info objectForKey:UIImagePickerControllerMediaMetadata]];
}
// Undocumented method guessing it rotates image to Portrait
pickedImage = [pickedImage IN_rotateToPortraitOrientation];
[metadata setImageOrientation:UIImageOrientationUp];
if (!assetsURL) {
[library writeImageToSavedPhotosAlbum:pickedImage.CGImage
metadata:metadata
completionBlock:^(NSURL *assetURL, NSError *error) {
$l(#"Saved to photo album");
}];
}
...
}
If you could help me understand the difference in meta data. If there is a difference how could I accomplish the same thing with PHPhotos.
Related
I want to saved an image in my photo albums, however I had succesfully saved the image but now I want to get the URL which would be my local URL that would open the image If I passes that to UIImage. I'm unable to get the saved image url as of error that "expression not allowed". How can I get the LOCAL URL of my saved image in iOS.
My Tried:
-(NSString *) imageSave: (UIImage *)image
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)image.imageOrientation completionBlock:^(NSURL *assetURL, NSError *error )
{
[library assetForURL:assetURL resultBlock:^(ALAsset *asset )
{
self.temp1 = [NSString stringWithFormat:#"%#",assetURL];
NSLog(#"SAVED!");
}
failureBlock:^(NSError *error )
{
self.temp1 = [NSString stringWithFormat:#"NO"];
NSLog(#"Error Saving Image!!!");
}];
}];
return self.temp1;
}
I tried by ma making a property but that returns null.
Try following code that may help you.
UIImage *viewImage = YOUR UIIMAGE // ---
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Request to save the image to camera roll
[library writeImageToSavedPhotosAlbum:[viewImage CGImage] orientation:(ALAssetOrientation)[viewImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
NSLog(#"error");
} else {
NSLog(#"url %#", assetURL);
NSString *myString = [assetURL absoluteString];
}
}];
I am having tough time with getting UIImagePickerController to work. It always crashes with memory error. These are the things I have done. Please advice what I can do differently.
I am using NSOperationQueue to do the save operation in a different thread.
I am not passing the UIImage which can be large, so I write the image to photo album and pass the NSURL of the asset.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:^{
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
NSMutableDictionary *mutable = [[info objectForKey:UIImagePickerControllerMediaMetadata] mutableCopy];
NSBlockOperation *saveOp = [NSBlockOperation blockOperationWithBlock:^{
[[MyViewController defaultAssetsLibrary] writeImageToSavedPhotosAlbum:[chosenImage CGImage] metadata:mutable completionBlock:^(NSURL *assetURL, NSError *error) {
if ([self.delegate respondsToSelector:#selector(imageSelected:)]) {
[self.delegate imageSelected:assetURL];
}
}];
}];
[saveOp setCompletionBlock:^{
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:saveOp];
}];
}
Im trying to save an AvAsset with multiple videos and merging them into a single video.
That part is taken care of though when the block completes it gives me an error.
My block:
-(void)exportDidFinish:(AVAssetExportSession*)session withCompletionBlock:(void(^)(BOOL success))completion {
self.exportSession = nil;
__block id weakSelf = self;
//delete stored pieces
[self.assets enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(AVAsset *asset, NSUInteger idx, BOOL *stop) {
NSURL *fileURL = nil;
if ([asset isKindOfClass:AVURLAsset.class])
{
AVURLAsset *urlAsset = (AVURLAsset*)asset;
fileURL = urlAsset.URL;
}
if (fileURL)
[weakSelf removeFile:fileURL];
NSLog(#"File Url: %#", fileURL);
}];
[self.assets removeAllObjects];
//[self.delegate removeProgress];
if (session.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error){
//delete file from documents after saving to camera roll
[weakSelf removeFile:outputURL];
if (error) {
completion (NO);
} else {
completion (YES);
}
}];
}
}
//Upload service
completion(YES);
[self.assets removeAllObjects];
}
This is the exact error I am receiving:
I would like to say I have a lot of experience with AVFoundation and the Assets though I do not and cant figure out why the completion block is failing.
What could be the issue and if you need anymore information let me know and i can update the question.
Turns out i had named my IBAction for the save button the name of the completionBlock so it was calling itself and failing.
Changed the name, and now it all works very good.
I am using following code to modify the metadata of Gallery Image.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)mediaInfo
{
ALAssetsLibrary *library =nil;
void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *) = ^(ALAsset *asset)
{
NSDictionary *metadata = asset.defaultRepresentation.metadata;
NSLog(#"Image Meta Data: %#",metadata);
NSMutableDictionary* dict=[[NSMutableDictionary alloc] initWithDictionary:metadata];
[dict setValue:#"sdfdfsfsfsfdsfsf" forKey:(NSString*)kCGImagePropertyIPTCKeywords];
UIImage *anImage = [mediaInfo valueForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation(anImage, 1.0);
[asset writeModifiedImageDataToSavedPhotosAlbum:imageData metadata:dict completionBlock:^(NSURL *assetURL, NSError *error) {
}];
};
NSURL *assetURL = [mediaInfo objectForKey:UIImagePickerControllerReferenceURL];
library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetURL
resultBlock:ALAssetsLibraryAssetForURLResultBlock
failureBlock:^(NSError *error) {
}];
}
But it is not working. Please help.
Here is a minimal example to do it:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *imageToSave = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
/* modify metadata dict */
NSMutableDictionary *imageMetadata = [[info objectForKey: UIImagePickerControllerMediaMetadata] mutableCopy];
NSLog(#"Inspect current metadata: %#", imageMetadata);
NSDictionary *iptc = #{(id)kCGImagePropertyIPTCKeywords: #"awesome photo"};
[imageMetadata setObject:iptc forKey:(id)kCGImagePropertyIPTCDictionary];
/* Save to the Camera Roll with modified medatadata */
[[ALAssetsLibrary new] writeImageToSavedPhotosAlbum:imageToSave.CGImage
metadata:imageMetadata
completionBlock:NULL];
[self performDismiss];
}
If you use a metadata viewer (OS X's Preview is good enough) you'll see something like this:
But, as pawan suggests, use an existing library to do it more easily. Google around, there are quite a few options out there.
I'm trying to save an image from camera to Photo Library and then store the URL of the saved image. My code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
[library writeImageToSavedPhotosAlbum:(__bridge CGImageRef)([info objectForKey:UIImagePickerControllerOriginalImage])
orientation:ALAssetOrientationUp completionBlock:^(NSURL *assetURL, NSError *error) {
if(error == nil) {
_myImageUrl = [NSString stringWithFormat:#"%#",assetURL];
NSLog(#"%#",assetURL);
} else NSLog(#"%#",error);
}];
[picker dismissViewControllerAnimated:YES completion:nil];}
My problem is that assetUrl is always NULL. Any ideas?
Thank you!
Finally, after reading more, I found out the answer: the first parameter of the function is of CGImageRef type and (__bridge CGImageRef) doesn't do what I expected; but if I call the CGImage method of UIImage object, it works. The correct way to do this is:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
CGImageRef image = [[info objectForKey:UIImagePickerControllerOriginalImage] CGImage];
[library writeImageToSavedPhotosAlbum:image
orientation:ALAssetOrientationUp
completionBlock:^(NSURL *assetURL, NSError *error) {
if(error == nil) {
_myImageUrl = [NSString stringWithFormat:#"%#",assetURL];
NSLog(#"%#",assetURL);
} else NSLog(#"%#",error);
}];
self.toDoImage.image = [info objectForKey:UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}