I currently sending ipa to friends for testing. Funny thing is, one of my tester able view her photos stored on her phone which was running IOS 5 using iPhone 4.
Another 2 testers: one has iPhone 4 (IOS 4.3.3) , and iPhone 3GS (IOS 5.0.1) both of them can't see photos stored on their phone.
These are the code I have used:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
//NSLog(#"See Asset: %#", #"ggg");
[assets addObject:result];
}
};
NSLog(#"location = %i length = %i ", range->location, range->length );
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
if(group != nil) {
NSRange *datarange = malloc(sizeof(NSRange));
range->total = [group numberOfAssets];
datarange->location = [group numberOfAssets] - range->location - range->length;
datarange->length = range->length;
NSLog(#" total = %i", range->total);
int location = [group numberOfAssets] - range->location - range->length;
if (location < 0)
{
datarange->location = 0;
datarange->length = [group numberOfAssets] - range->location;
}
NSIndexSet *indexset = [ [NSIndexSet alloc] initWithIndexesInRange:*datarange];
[group enumerateAssetsAtIndexes:indexset options:NULL
usingBlock:assetEnumerator];
[indexset release];
free(datarange);
[self loadAssetToScrollView:assets];
}
};
[assets release];
assets = [[NSMutableArray alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failure");
}];
[library release];
I saw somebody say about asynchronous thing in some other threads but don't know is it the case. He say put dispatch_async in the enumerate group block.
Does anyone know what is wrong.
Additionally, one of tester with iOS 4.3.3 can show his photos after enabling location services under General->Setting. Why we have to enable it? Can we enabled it on code since it will be quite disturbing to the user who using our application.
Also on iOS 5.x you must retain your ALAssetsLibrary instance so long as you need to work with the collected assets. When you release your ALAssetsLibrary instance like in your code just after calling [library enumerateGroupsWithTypes:…] all the collected assets will be invalid.
See also the ALAssetsLibrary doc - overview:
"… The lifetimes of objects you get back from a library instance are tied to the lifetime of the library instance. …"
Yes, it is incredibly frustrating, but that is how it is, and you cannot enable location services in code (that is a good thing though).
I would move the first block ^assetGroupEnumerator to the heap by [[<#block#> copy] autorelease]. Why? Because this block would be autoreleased by the runloop, if there are many assets need to be enumerated through.
One more thing: don't use [self loadAssetToScrollView:assets]; inside the block but get the weak reference of self before the block like this:
__block YourExampleClassInstance *weakSelf = self;
and further use this weakSelf instance inside the block:
[weakSelf loadAssetToScrollView:assets];
void (^assetGroupEnumerator)… = ^(ALAssetsGroup *group, BOOL *stop) {
…
};
Why? To avoid retain cycles.
Related
I'm using the following code to access all ALAssetsLibrary images but the ALAssetsLibrary is giving me the saved video thumbnail images with the saved images from ALAssetsLibrary. how can i prevent this using the code so that i can get only saved images?
//Method to get all images from devices library
- (NSMutableArray*)getAllImagesFromLibrary
{
//get all images from image library
void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
//Insert objects into array
[self.arrOfAllImages addObject:result];
}
};
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
if(group != nil) {
[group enumerateAssetsUsingBlock:assetEnumerator];
}
};
//NSMutableArray allacation
NSMutableArray *arrOfAllImage = [[NSMutableArray alloc] init];
static dispatch_once_t pred = 0;
static ALAssetsLibrary *library = nil;
dispatch_once(&pred, ^{
library = [[ALAssetsLibrary alloc] init];
});
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failure");
}];
return arrOfAllImage;
}
Set a filter before you enumerate:
[group setAssetsFilter: [ALAssetsFilter allPhotos]];
Check your result, If it will image the add in array otherwise not
void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto])
{
//Insert objects into array
[self.arrOfAllImages addObject:result];
}
}
};
You can mention many types of Asset through ALAssetsGroupType
They are
ALAssetsGroupLibrary
ALAssetsGroupAlbum
ALAssetsGroupEvent
ALAssetsGroupFaces
ALAssetsGroupSavedPhotos
ALAssetsGroupPhotoStream
ALAssetsGroupAll
1
ALAssetsGroupLibrary
The Library group that includes all assets that are synced from
iTunes.
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
2
ALAssetsGroupAlbum
All the albums created on the device or synced from iTunes, not
including Photo Stream or Shared Streams
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
3
ALAssetsGroupEvent
All events, including those created during Camera Connection Kit
import.
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
4
ALAssetsGroupFaces
All the faces albums synced from iTunes.
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
5
ALAssetsGroupSavedPhotos
All the photos in the Camera Roll.
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
6
**ALAssetsGroupPhotoStream**
The PhotoStream album.
In iOS 6.0 and later, this also includes Shared Streams.
Available in iOS 5.0 and later.
Declared in `ALAssetsLibrary.h`.
7
ALAssetsGroupAll
The same as ORing together all the group types except for
ALAssetsGroupLibrary.
Available in iOS 4.0 and later.
Declared in ALAssetsLibrary.h.
You can see more details developer.apple
Example:
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failure");
}];
In my app, i have Used UiimagepickerController for taking Video.in bettween my programm received any web service Which belongs to my app,
i have to stop Video Capture and save video.
i have Used StopVideoCapture to do above thing ,but it doesn't call delegate - `
(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
How to force call above delegate ??.or How to handle interruption Handling inUIImagePickerController`.. any idea?
The idea with delegate methods is not that you call those methods - "They call you".
So I would not consider calling the delegate method yourself a good practise. However, if you present the UIImagePickerViewController with a modal dialogue (which I guess is common for such a picker) then you can close it like this outside of your delegate method:
[[yourPicker parentViewController] dismissModalViewControllerAnimated:YES];
Source
Update: You can use the ALAssetsLibrary for accessing the stored data in your iPhone media library. I recently had to do a similar project where I had to list all images on the iPhone. The Github project ELCImagePickerController.git was very useful since it shows how the items in your library can be accessed. So you'll do something like this:
#import <AssetsLibrary/AssetsLibrary.h>
// ....
-(void)fetchPhotoAlbums{
if(!self.assetsGroups){
self.assetsGroups = [NSMutableDictionary dictionary];
}
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
#autoreleasepool {
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop){
if (group == nil){
// Completed
[self.delegate pictureService:self fetchedAlbums:returnArray];
return;
}
Album *currentAlbum = [self albumForAssetsGroup:group];
// Store the Group for later retrieving the pictures for the album
[self.assetsGroups setObject:group forKey:currentAlbum.identifier];
[returnArray addObject:currentAlbum];
[self.delegate pictureService:self fetchedAlbums:returnArray];
};
void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
NSLog(#"A problem occured %#", [error description]);
};
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:assetGroupEnumerator
failureBlock:assetGroupEnumberatorFailure];
}
}
-(void)fetchPhotosForAlbum:(Album *)album{
ALAssetsGroup *currentGroup = [self.assetsGroups objectForKey:album.identifier];
NSMutableArray *photos = [NSMutableArray array];
[currentGroup enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if(asset == nil){
[self.delegate pictureService:self fetchedPictures:photos forAlbum:album];
return;
}
[photos addObject:[self pictureForAsset:asset]];
}];
}
Additionally I use two mapper methods to convert the AL-classes into my own model classes.
- (Album *)albumForAssetsGroup:(ALAssetsGroup *)assetsGroup{
Album *album = [[Album alloc] init];
album.title = [assetsGroup valueForProperty:ALAssetsGroupPropertyName];
album.identifier = [assetsGroup valueForProperty: ALAssetsGroupPropertyPersistentID];
album.assetsCount = assetsGroup.numberOfAssets;
album.thumbnail = [UIImage imageWithCGImage:assetsGroup.posterImage];
return album;
}
- (Picture *)pictureForAsset:(ALAsset *)asset{
Picture *picture = [[Picture alloc]init];
picture.identifier = [((NSArray *)[asset valueForProperty: ALAssetPropertyRepresentations]) objectAtIndex:0];
picture.thumbnail = [UIImage imageWithCGImage:asset.thumbnail];
return picture;
}
See the AssetsLibrary Documentation
please help me with my question:
Can I give URLs and metadata for all the images/videos in iPhone library with ALAssetsLibrary?
Can I edit/delete these images/videos?
the above code has missed some braces so it is resolved below
ALAssetsLibrary *al = [[ALAssetsLibrary alloc] init];
assets = [[NSMutableArray alloc] init];
[al enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
NSLog(#"%#",asset);
NSLog(#".. do something with the asset");
}
}
];
}
failureBlock:^(NSError *error)
{
// User did not allow access to library
// .. handle error
}
] ;
Take a look at the documentation for ALAssetsLibrary here. To access all photos and videos you need to enumerate all groups (albums) in the photo library and then enumerate all photos and images in each group. You cannot delete assets using the API. iOS 5 adds extra functionality - it's still under NDA though and cannot be discussed here - have a look at the beta documentation and Apple Developer forums for iOS5.
Your code will need to do something like this:
ALAssetsLibrary *al = [[ALAssetsLibrary alloc] init];
[al enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
.. do something with the asset
}
}
];
}
failureBlock:^(NSError *error)
{
// User did not allow access to library
.. handle error
}
];
i have to fetch all photos from the iphone gallery without open the imagepickercontroller. if any have any idea or reference then post here and help me to complete my task.
Thanks in advance
Ravi
You can use ALAssetsLibrary for that. Keep in mind that users have to grant your application access to the location services to be able to "read" the items in your library. Try this piece of code and let me know if it works:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryGroupsEnumerationResultsBlock successBlock = ^(ALAssetsGroup *group, BOOL *stop) {
if (group != nil) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result != nil) {
// do something with your asset
}
}];
}
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
NSLog(#"Could not enumarate assets. Reason: %#", error);
};
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:successBlock failureBlock:failureBlock];
[library release];
You can also read this for more details. Also, don't forget to add #import <AssetsLibrary/AssetsLibrary.h> in your .h file and link the AssetsLibrary.framework to your project before.
Let me know if that helps!
I tried to use ALAssetLibrary to get albums and photos. This is my code:
void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
NSLog(#"See Asset: %#", result);
}
};
void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
if(group != nil) {
[group enumerateAssetsUsingBlock:assetEnumerator];
}
};
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failure");
}];
I'm getting exc_bad_access on : [group enumarateAssetsUsingBlock:assetEnumerator] and the group is not nil.
The strange thing is that this code is working if I create a new project, but in my old project it's not working.
SDK version is iOS 4.3
Tested on iPhoneSimulator 4.3
Can anyone could give me an ideea of what's happening?
Thanks.
As you crash on the one project but not on the other, are you sure the settings and configurations are appropriate?
In particular:
Check that the TARGET_DEPLOYMENT_OS is set to the minimum version the ALAsset framework is available.
Check that you have included all the requested frameworks (even if the linker should warn about this if you forgot to include it)
Moreover, the details of the crash (crashlog, exception details, ...) would be helpful if any.
Also are you sure the ALAssetLibrary isn't released before the enumeration (which is probably done asynchnously) ends? There is no release in your code in your question but maybe there is one in your real code?
AFAIK, enumerateGroupsWithTypes: executes its block on a secondary thread in an asynchrnous way (see this other question on SO), so that's probably your problem (you are trying to use a group that has been released from memory since you start your enumeration, you have to be sure the ALAssetLibrary is still in memory until the enumeration is done)