enumerateAssetsWithOptions return an alasset nil - ios

i'm getting the user ALAssetsLibrary with this code
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just photos.
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
// Chooses the photo at the last index
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
// The end of the enumeration is signaled by asset == nil.
if (alAsset) {
The problem that from time to time the alasset returns as a nil and i have no idea why. Most of the phones i tried it on, it was working fine but for some reason, other phones the alasset just returning as a nil.

iOS8 introduced the new Photos Framework. Many assets that used to be stored locally on the device are now stored in iCloud (i.e. not on the device). The Photos Framework is intended to be used when interacting with these assets (assets that may or may not be on the device).
My guess is that ALAssetLibrary returns nil for assets not stored locally on the device. Hence the issue you're encountering.
I have heard recently that iOS 8.1 rolled back this iCloud-related change, although I haven't been able to verify myself.
Hope this helps.

Related

No slow motion effect in exported from camera roll video on iPhone 6/6+

I'm developing app that works with video. It makes short movies from recorded or exported from camera roll videos. I need help with some unexpected behavior.
When I export video recorded with apple slow motion effect - such effect is lost in video in my app.
This's reproduced on iPhone 6 and 6+ and I assume on iPhone 5s too. On iPhone 5s/6/6+ Simulator, everything is ok. To export video I use iOS SDK ALAssetsLibrary API, code:
NSMutableArray* allVideos = [[NSMutableArray alloc] init];
self.assetLibrary = [[ALAssetsLibrary alloc] init];
[self.assetLibrary enumerateGroupsWithTypes: ALAssetsGroupAll
usingBlock: ^(ALAssetsGroup* group, BOOL* stop1){
if (group) {
[group setAssetsFilter: [ALAssetsFilter allVideos]];
[group enumerateAssetsUsingBlock: ^(ALAsset* asset, NSUInteger index, BOOL* stop2){
if (asset) {
[allVideos addObject: asset];
}
}];
}
else {
//sort by last shooted video
self.view.videoAssetRepresentations = [allVideos sortedArrayUsingComparator: ^NSComparisonResult (ALAsset* obj1, ALAsset* obj2) {
return [[obj1 valueForProperty: ALAssetPropertyDate] timeIntervalSince1970] < [[obj2 valueForProperty: ALAssetPropertyDate] timeIntervalSince1970];
}];
}
}
failureBlock: ^(NSError* error){
DbgLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
To play exported video I use AVPlayer instance.
Please help me - how can I solve my problem?
PS - Instagram app can do this, tested on iPhone 6. Exported video contains slow motion effect inside Instagram app.
See: https://devforums.apple.com/message/1025773#1025773
It seems that you cannot do this with the ALAssetsLibrary. However, with the new Photos framework for iOS 8+ you can use PHAssetMediaSubtypeVideoHighFrameRate

Retrieving videos uploaded from iTunes

I am creating an app that fetches photos and videos from the library.
I am using ALAssetsLibrary to fetch the contents from the library. But I can't retrieve the videos album from the library using this.
I am using the following code to retrieve the contents:
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group || group.numberOfAssets >= 1)
{
[tmpAssets addObject:group];
}else{
self.assetAlbums = tmpAssets;
*stop = YES;
if(self.assetAlbums.count){
//parse contents and reload view
}
}
}
failureBlock:^(NSError *error)
{
//failed
}];
I am getting all other pictures and videos.
I have used a workaround of creating one videos album and filling its contents with the results from the ALAssetsLibraryGroupsEnumerationResultsBlock with allVideos filter.
but the ones that I upload from iTunes (those that get into the videos folder in the library) are not getting retrieved.

IOS - Can i detect if a photo was taken by regular iphone app camera or by a third party application?

I'm building an IOS applicaiton.
I'm want to get the last photo that was taken that was also took from the rugular iphone app camera and not by a third party application.
I can get the last photo from the photo library by this method:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just photos.
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
// Chooses the photo at the last index
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
// The end of the enumeration is signaled by asset == nil.
if (alAsset) {
ALAssetRepresentation *representation = [alAsset defaultRepresentation];
UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]];
// Stop the enumerations
*stop = YES; *innerStop = YES;
Can i some how detect if this photo was taken by the regular iphone camera applicaiton?

ALAssetsLibrary get all videos

I am making a camera app where I want to get to all of the videos users have created on their iPhone.
Currently the code I have gets the videos from user Camera Roll only. Some my users have complained that they have multiple custom folders created under their Photo Album app and they store some videos in there. Since my code only looks at Camera Roll, it doesn't pickup the movies from their other folders. Is it possible that I can get to their other folders?
This is what I have so far.
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsUsingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop)
{
if (alAsset)
{
ALAssetRepresentation *representation =[alAsset defaultRepresentation];
NSURL *url = [representation url];
NSString *assetType=[alAsset valueForProperty:ALAssetPropertyType];
//videos only
if ([assetType isEqualToString:#"ALAssetTypeVideo"])
{
.....
You got to create a filter for the assets, something like this:
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
ALAssetsFilter *allVideosFilter = [ALAssetsFilter allVideos];
[group setAssetsFilter:allVideosFilter];
//...
};
Options for filters are:
- allAssets
- allVideos
- allPhotos
Hope this helps
To get media that was synced from iTunes you need to use ALAssetsGroupLibrary. Here you can find all possible variants for ALAssetsGroupType. So just change
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:...
to
[library enumerateGroupsWithTypes:(ALAssetsGroupSavedPhotos | ALAssetsGroupLibrary) usingBlock:...
This retrieves all videos, including any the user has synced from iTunes:
// Enumerate just the photos and videos by using ALAssetsGroupSavedPhotos
[library enumerateGroupsWithTypes:ALAssetsGroupAll | ALAssetsGroupLibrary
usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group != nil)
{
// Within the group enumeration block, filter to enumerate just videos.
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result) {
// Do whatever you need to with `result`
}
}];
} else {
// If group is nil, we're done enumerating
// e.g. if you're using a UICollectionView reload it here
[collectionView reloadData];
}
} failureBlock:^(NSError *error) {
// If the user denied the authorization request
NSLog(#"Authorization declined");
}];
Note the ALAssetsGroupAll | ALAssetsGroupLibrary.
According to the docs ALAssetsGroupAll is "the same as ORing together all the group types except for ALAssetsGroupLibrary". So we also add ALAssetsGroupLibrary which "includes all assets that are synced from iTunes".

Memory problems while reading iphone camera roll with AlAssetsLibrary

I'm trying to get last picture from iphone camera roll. I use the following code:
UIImage* __block image = [[UIImage alloc] init];
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup* group, BOOL* stop) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
if ([group numberOfAssets] > 0) {
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:[group numberOfAssets]-1] options:NSEnumerationConcurrent usingBlock:^(ALAsset* alAsset, NSUInteger index, BOOL* innerStop) {
if (alAsset) {
ALAssetRepresentation* rawImage = [alAsset defaultRepresentation];
image = [UIImage imageWithCGImage:[rawImage fullScreenImage]];
[self doTheJobWithImage:image];
// Inside doTheJobWithImage: a segue is also performed at the end
}
}];
}
} failureBlock:^(NSError* error) {
NSLog(#"Error: %#", [error localizedDescription]);
}];
It works but with flaws (I'm using Instruments and Zombies to debug it):
It seems to read every picture inside camera roll. So, first question: doesn't enumerateAssetsAtIndexes: only retrieve the specified images (atIndexes)? What's wrong with my code?
Adding to previous problem, memory becomes a problem when a lot of pictures are in camera roll. My app crashes if too many or, if it works, it seems retrieved images are NEVER deallocated, so the second or third time i call this code, it crashes anyway due to memory leaks. So second question: how do I force my code to deallocate everything after calling doTheJobWithImage: ?
I'm using xcode 4.6, ios 6 and ARC. Thanks in advance.
After few hours, I figured out that nothing is wrong with the code here. It is the right code to extract last picture in camera roll (if somebody ever needs it). The problem was inside doTheJobWithImage: , I solved it replacing
[self doTheJobWithImage:image];
and storing the resulting image somewhere else, and THEN performing doTheJobWithImage: after picture enumeration was done.. Saying this just in case somebody else is interested.

Resources