requestImageDataForAsset fails with no error

I'm occasionaly seeing requestImageDataForAsset return nil for imageData and no error in the info dict. I have also noticed that when this happens there's a little icon in the Photos app (You'll also note how bllurry the photo is). Sometimes tapping this icon helps. I'd sure like to know what tapping the icon does and what other folks are doing.




@implementation PHAsset (ImageIOBits)
-(void) writeAssetToPath:(NSString*)path completion:(PHAssetWrite)completion
{
  PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
  options.synchronous = NO;
  options.networkAccessAllowed = YES;
  options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
  dispatch_async(dispatch_get_main_queue(), ^{
  [ECPActivityIndicator displayActivity:NSLocalizedString(@"iCloud Photo",@"progress indicator") withProgress:progress];
  });
  };

  [[PHImageManager defaultManager] requestImageDataForAsset:self options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
  BOOL success = NO;
  if(imageData){
  if(![ECPActivityIndicator isHidden])
  [ECPActivityIndicator displayCompleted:NSLocalizedString(@"Download Complete", @"progress indicator")];
  success = [imageData writeToFile:path atomically:YES];
  }else{
  if(![ECPActivityIndicator isHidden])
  [ECPActivityIndicator displayCompleted:NSLocalizedString(@"Trouble Retreiving Photo", @"progress indicator")];

  if (info[PHImageErrorKey]) {
  NSError* err = info[PHImageErrorKey];
  err = err.userInfo[NSUnderlyingErrorKey] ? err.userInfo[NSUnderlyingErrorKey] : err;
  [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Uh oh", @"Alert title Unexpected results")
  message:[NSString localizedStringWithFormat:NSLocalizedString(@"The photo could not be opened. - %@",
    @"Alert message - param is name of some error."),
  [err localizedDescription]]
    delegate:self
    cancelButtonTitle:NSLocalizedString(@"OK", @"Alert Button saying continue accept or acknowlege.")
    otherButtonTitles: nil] show];

  }
  }
  completion(success);
  }];
}
@end

Replies

this editor is terrible. I couldn't insert a photo so I hosted it elsewhere and went into html mode and added a pic of the icon. It previewed fine, but stripped it out.


http://s23.postimg.org/6ai19sacb/mystery_Icon.jpg


ugh

In trying to resolve this I'm looking at enabling iCloud Photo logging. (https://developer.apple.com/bug-reporting/ios/icloud/#icloud-photo-library)


It seems that I can't install this profile under IOS9, and my only ios8 device left is the one will all the origional photos on it. Has anyone managed to install the logging tools on IOS9?

Do you have a bug number for this specific issue or have you also found that it is related to "Storage Optimization" settings as described here: https://openradar.appspot.com/21930581

This is something I'm following up on with Photos framework engineering but don't really have anything concreet back at this time, seems like everyone is in information gathering mode trying to figure out exactly what's going on.

I don't have a bug number as I don't have a concrete set of steps or error to go along with it.


Here's what I can confirm. The trouble occurs on a device that is currently downloading a very large iCloud Photo Library. This device does have storage optimization turned on, and the effected assets are not on the device at full resolution. In our custom photo picker, you can long press to view an image full screen. Even for affected assets, we don't have any trouble reciving a larger, screen sized rendition (and it pulls this over the network). But when we request the full data on affected assets, photokit fails to return the image or an error no matter if network access is enabled or not. I've tried repeating the requests and it get the same result. At times, the odd icon that I posted above appears in the Photos app and tapping it resolves the trouble. At times, just visiting the photo in the Photos app solves it.


If PhotoKit logging was availible to IOS9 I'd probably have something concrete... perhaps I'll downgrade this device and give the logging a go.

Well I decided to go the extra mile and downgrade a device, restore all the stuff i would need and get to where i could reproduce the problem.... and the profile at this link:


https://developer.apple.com/bug-reporting/ios/icloud/#icloud-photo-library


is no longer valid.


<Notice>: (Error) MC: Install profile data, interactive error. Error: NSError:

Desc : Profile Installation Failed

Sugg : The profile “Cloud Photo Library Diagnostics Profile” is no longer valid.

US Desc: Profile Installation Failed

US Sugg: The profile “Cloud Photo Library Diagnostics Profile” is no longer valid.

Domain : MCInstallationErrorDomain

Code : 4001

Type : MCFatalError

...Underlying error:

NSError:

Desc : The profile “Cloud Photo Library Diagnostics Profile” is no longer valid.

US Desc: The profile “Cloud Photo Library Diagnostics Profile” is no longer valid.

Domain : MCInstallationErrorDomain

Code : 4026

Type : MCFatalError

Params : (

"Cloud Photo Library Diagnostics Profile"

A download from the network will only happen ‘on demand’ when the ‘optimize’ mode is on.

The only suggestion from engineering at this time is to retry the request on the API side when you notice this situation. However, as it sounds like you've already implemented this technique I really encourage you to collect as much detail as possible and file a bug regardless of how you feel about the amount of information you have - The team really stressed the importance of having a bug for this, so please file it and post the number here for the record - The team is already aware of this discussion.


Thank you!

Filed bugreport #24573250 on this.

No workaround or solution yet?

    func requestImageDataBug() {

        let fetchOptions = PHFetchOptions()
        let byDateReverse = NSSortDescriptor(key: "modificationDate", ascending: false)
        fetchOptions.sortDescriptors = [byDateReverse]

        // / returns all PHAssets (photos) in a PHFetchResult - small sets of photos doesn't demonstrate the bug - 800+ failing in tests on iOS 9.2.1 iPhone 6+
        let photos = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)

        let requestOptions = PHImageRequestOptions()

        // use synchronous to avoid trying to load 1000+ images at once
        requestOptions.synchronous = true

        photos.enumerateObjectsUsingBlock({ (asset, i, info) -> Void in
            print("Index: \(i)")
     
            if let asset = asset as? PHAsset {
                PHImageManager.defaultManager().requestImageDataForAsset(asset, options: requestOptions, resultHandler: { (nsData, string, orientation, info) -> Void in
             
                    if nsData != nil {
                        print("ok - \(info)")
                    } else {
                        print("!!! - Nil image - \(info)")
                    }
                })
            } else {
                /
                print("No asset")
            }
     
        })

        print("Golly, you didn't crash!? - did you add enough images to the camera roll, fix the issue (bug)?  Add another few thousand decent sized images to the camera roll and give it another go.  ")

    }


Here's a Swift version demonstrating the reproducible crash using requestImageDataForAsset with a variety of out of memory type messages. Interestingly the app itself only uses 12mb of memory at peak.


Console log show the following type of messages:


libBacktraceRecording.dylib: allocate_free_list_pages() -- virtual memory exhausted!

warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.


-or-


libBacktraceRecording.dylib: allocate_free_list_pages() -- virtual memory exhausted!


-or-


RequestImageBug(9083,0x1a0f29000) malloc: *** mach_vm_map(size=1048576) failed (error code=3)

*** error: can't allocate region securely

*** set a breakpoint in malloc_error_break to debug

RequestImageBug(9083,0x1a0f29000) malloc: *** mach_vm_map(size=1048576) failed (error code=3)

*** error: can't allocate region securely

*** set a breakpoint in malloc_error_break to debug

warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.

(lldb)

This may not be exactly the same issue as yours, but the high level symptoms were similar where

requestImageDataForAsset
returned nil image data but was also accompanied by a console error message like this:

[Generic] Failed to load image data for asset <PHAsset: 0x13d041940> 87CCAFDC-A0E3-4AC9-AD1C-3F57B897A52E/L0/001 mediaType=1/0, sourceType=2, (113x124), creationDate=2015-06-29 04:56:34 +0000, location=0, hidden=0, favorite=0 with format 9999


In my case, the problem suddenly started happening on a specific device only with assets in iCloud shared albums after upgrading from iOS 10.x to 11.0.3, and since then through to 11.2.5. Thinking that maybe

requestImageDataForAsset
was trying to use files locally cached in
/var/mobile/Media/PhotoData/PhotoCloudSharingData/
(from the info dictionary's
PHImageFileURLKey
key) and that the cache may be corrupt I thought about how to clear that cache.


Toggling the 'iCloud Photo Sharing' switch in iOS' Settings -> Accounts & Passwords -> iCloud -> Photos seems to have done the trick.

requestImageDataForAsset
is now working for those previously failing assets.