The application I am working on manipulates an image for a user, and after the user is done, they can save that photo. I have no problem capturing the screen and saving it (as I want some of the labels saved with the image) but this call:
UIImageWriteToSavedPhotosAlbum([self getScreenAsImage] , nil, nil, nil);
only appears to allow me to save to the 'Saved Photos' album. Ideally I would like to create an album named after the application I am working on and save it there so that they are all stored together (for example like the Hawaii or graduation day albums on the simulator). It would also be nice then to launch the image picker in that specific album. Anyone know how to do this? Most important part is to be able to save it in an album, being able to launch the picker in that album is of secondary importance.
There is a way to do it, Apple just hasn't made it simple.
There is a custom category that adds the functionality to ALAssetsLibrary.
Git repo for the category can be found here
and if you are using Cocoapods you can get it with
pod 'ALAssetsLibrary-CustomPhotoAlbum'
You will need to instantiate a ALAssetsLibrary object and call the method below
- (void)saveImage:(UIImage *)image
toAlbum:(NSString *)albumName
completion:(ALAssetsLibraryWriteImageCompletionBlock)completion
failure:(ALAssetsLibraryAccessFailureBlock)failure
Something like below
Import:
#import "ALAssetsLibrary+CustomPhotoAlbum.h" //Source Included (Git)
or
#import <ALAssetsLibrary+CustomPhotoAlbum.h> //Cocoapods
Call:
ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
[assetsLib saveImage:imageToSave
toAlbum:#"AlbumName"
completion:completionBlock
failure:failureBlock];
You can use the ALAssetsLibrary for doing this:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library saveImage:image toAlbum:#"Midhun" withCompletionBlock:^(NSError *error) {
if (error!=nil) {
NSLog(#"Error: %#", [error description]);
}
}];
Check this tutorial also: Custom Photo Album
To the best of my knowledge Apple has not exposed an SDK to allow for this. After a review the UIKit function reference, My fear seems confirmed.
Related
Posted this on Apple with no luck, but now that the iOS 6 NDA is up, hoping more eyes will see it here.
I am attempting to modify an app to only allow a user to select music that has been downloaded locally. I have the following code under iOS 6 GM:
MPMediaPickerController* mpc = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio];
mpc.allowsPickingMultipleItems = YES;
mpc.modalPresentationStyle = UIModalPresentationCurrentContext;
mpc.showsCloudItems = NO;
[self presentViewController:mpc animated:YES completion:nil];
From the documentation:
The default behavior for a media item picker is YES, which means the
the picker shows available iCloud items. A media item is considered an
iCloud item if it is available via iTunes Match and is not already
stored on the device.
I take this to mean that if iTunes Match is enabled, only items that have been downloaded to the device will show in the picker, however I always see the entire iTunes Match library. I filed a radar for this, because it seems like a serious bug. If anyone can tell me otherwise, I'd love to know what I'm missing here.
This seems to be an OS problem.
Using picker.showsCloudItems = NO; correctly shows fewer songs, instead of the whole list... The songs listed there are songs that either were manually downloaded in the Music app or songs that were streamed and therefore cached.
The problem, at least in my case, is dealing with the cached ones.
If I select a song that was manually downloaded the value of MPMediaItemPropertyIsCloudItem is NO, which is correct. I can also access the asset's URL through the MPMediaItemPropertyAssetURL property.
On the other hand, selecting a song that was cached returns YES on MPMediaItemPropertyIsCloudItem and nil on MPMediaItemPropertyAssetURL, making the song virtually useless to me.
Sorry I don't have an actual answer but I don't have enough reputation to simply comment.
Hope my 2 cents help somehow, but it truly seems to me that this issue can only be resolved by Apple in a future update.
A better solution to test if an item comes from iCloud in the didPickMediaItems delegate:
MPMediaItem *selectedItem = [selectedItems objectAtIndex:0];
if (![[selectedItem valueForProperty:MPMediaItemPropertyIsCloudItem] boolValue])
You don't really need to play it, it is more efficient to use the embedded property in the MPMediaItem.
I had this same problem. Although I was unable to hide the items, here's a good workaround that I used to prevent people from being able to select them. Inside didPickMediaItems, you should temporarily load it into an AVPlayerItem and then just check the validity of that item like so:
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
MPMediaItem *selectedItem = [[mediaItemCollection items]objectAtIndex:0];
NSURL *tempURL = [selectedItem valueForProperty:MPMediaItemPropertyAssetURL];
AVPlayerItem *playerItem = [[AVPlayerItem alloc]initWithURL:tempURL];
if(playerItem.loadedTimeRanges==NULL)
{
UIAlertView *alert=[[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"Invalid Song Choice",NULL) message:NSLocalizedString(#"Please choose a song that is local to your phone.",NULL) delegate:self cancelButtonTitle:NSLocalizedString(#"Okay",NULL) otherButtonTitles:nil]autorelease];
[alert show];
[playerItem release];
}
else
{
NSLog(#"Your good to go...do whatever you want with the local song");
}
}
It appears to be fixed in iOS 7.
The following code works; iCloud items are not showing:
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker.delegate = self;
picker.allowsPickingMultipleItems = NO;
picker.showsCloudItems = NO;
Could anyone perhaps tell me how exactly I could get a handle on an image that the user has just taken with the device camera? For instance, when the user captures an image, it is saved to the photo library, but you don't know the exact name of the image file without going to the photo library an searching for the image. I want to get a handle on the image once it is taken and then pass it to an UIImage so that I could for instance immediately display it to the user.
Thank you
You have 2 options depending on what method you are using to capture the image.
If you are using the UIImagePickerController to capture a still image with the UIImagePickerControllerSourceTypeCamera set as the source. You will recieve a call to your DELEGATE when the picture has been taken.
- (void) imagePickerController: (UIImagePickerController *) picker
didFinishPickingMediaWithInfo: (NSDictionary *) info
Here you can find the picture which you can use to present it directly. (The picture is in the "info" dictionary)
https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/CameraAndPhotoLib_TopicsForIOS/Articles/TakingPicturesAndMovies.html#//apple_ref/doc/uid/TP40010406
Check the code on that apple site to see how it is implemented.
Alternatively method number 2 is by using the AVFoundation Framework. However this requires you to configure much more even though it gives you more freedom to how you can set things.
At the end of the implementation you will get the picture like this:
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:
^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
CFDictionaryRef exifAttachments =
CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments) {
// Do something with the attachments.
}
// Continue as appropriate.
}];
Here the image is in the imageSamplerBuffer.
This approach can be found here: https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html
Hello I need to use the uiimagepickercontroller to get the photo from the photo library in IOS 3. I managed to get the original image and custom coding to generate the thumbnail from the original image.
Is there a way of fetching the thumbnail that was used in the UIImagePickerController? I can generate thumbnail from original image but it will slow down the whole process. At the time, is there a way of saving the url of the original image. At the moment, I am just create a new image and saved on a temporary folder for later app to upload the server. The process is too slow since I need to generate thumbnail as well as creating the original image.
in ios 3.0 , their is no direct way to get thumbnail, you have to do custom coding to get thumbnail .
from version 4.0 we have ALAssetsLibrary.
ALAssetsLibrary *assetslibrary = [self defaultAssetsLibrary];
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset){
CGImageRef thumbnailRef = [myasset thumbnail]; //gives thumbnail
}
[assetslibrary assetForURL:asseturl resultBlock:resultblock failureBlock:^(NSError *error) {
//handle error
}];
but cons of above method is if used declined access to library then you have to handle error and again get thumbnail again with custom coding .
please update if you have find any better method .
I am writing an app that is a clone of the UIImagePicker but uses the Assets library. When the user selects a photo, it takes a little bit too long for the image to load. I notice that when I use the photos app which has identical functionality as to what I'm developing, that the image loading is a bit faster. I've heard another responder on this site mention the following in order to mimic the functionality of the photos app:
"Load the thumbnail image first (best with dispatch_async) - that should be really quick. When this has completed, load the fullscreen image like you did above. This is what apple does in the Photo App to provide a smooth user experience."
Does anyone have any code samples of how this can be accomplished? I'm not quite sure that I understand what he means.
Also here is my code for which I'm using to load an image (I'm passing the image as a parameter to another view controller):
myImage = [UIImage imageWithCGImage:[[myAsset defaultRepresentation] fullScreenImage]];
The class ALAsset has two methods to obtain thumbnails:
- (CGImageRef)thumbnail
- (CGImageRef)aspectRatioThumbnail
I bet they are faster than obtaining the full screen sized version of the asset.
Also, you can wrap them with an async operation. Be sure to update the UI in main thread. Roughly like this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* obtain the image here */
dispatch_async(dispatch_get_main_queue(), ^{
/* update screen here */
});
[pool drain];
});
If you need to obtain thumbnails for videos you should use AVAssetImageGenerator. It has a method to obtain them asynchronously.
Look for Apple sample code (AVEditDemo and probably others working with assets library).
When i run the following code:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:albumCopy
resultBlock:^(ALAsset *asset) {
...
}
failureBlock:^(NSError *error) {
...
}];
[library autorelease];
the app asks the user for permission to use their current location. I don't use their current location in any way, so is there a way to stop it from asking the user? I know those messages always detract from the user experience.
Thats not possible, Apple did this because the EXIF data of the photos contains the location and they don't have a way to request everything but the location tag from the photos. File a bug report, maybe they will implement something like this in a future iOS version.