We implemented the new PHPicker and have run into an issue we haven't been able to replicate on our own devices but see a lot of users running into it. The problem is an error after getting the PHPickerResults and trying to get the UIImages.
Because the user can select several images at once, what we do is get the results and iterate over each itemProvider object.
I'm following apple's guidance and checking if itemProvider canLoadObjectOfClass:UIImage.class, before executing itemProvider loadObjectOfClass:UIImage.class.
However we are getting hundreds of reports of users where this last method returns an error.
Firstly, this is how we configure our PHPickerViewController:
And this is what we do with the PHPickerResult. This is a method that returns a block with an array of an object NewPicture instantiated with the UIImage I should be getting.
The most common error we see our users are getting is:
I'm having a really hard time understanding why this sometimes fails. I'd really appreciate it if someone could give me a hand with this.
I'm attaching the stack trace:
Because the user can select several images at once, what we do is get the results and iterate over each itemProvider object.
I'm following apple's guidance and checking if itemProvider canLoadObjectOfClass:UIImage.class, before executing itemProvider loadObjectOfClass:UIImage.class.
However we are getting hundreds of reports of users where this last method returns an error.
Firstly, this is how we configure our PHPickerViewController:
Code Block PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init]; configuration.selectionLimit = self.pictureSelectionLimit; configuration.filter = PHPickerFilter.imagesFilter; configuration.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent; PHPickerViewController *pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:configuration]; pickerViewController.delegate = self; pickerViewController.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:pickerViewController animated:YES completion:nil];
And this is what we do with the PHPickerResult. This is a method that returns a block with an array of an object NewPicture instantiated with the UIImage I should be getting.
Code Block NSMutableArray *picArray = [[NSMutableArray alloc] init]; NSArray *itemProviders = [self.results custom_map: ^id _Nullable (PHPickerResult *_Nonnull current) { return current.itemProvider; }]; dispatch_group_t dispatchGroup = dispatch_group_create(); for (NSItemProvider *itemProvider in itemProviders) { dispatch_group_enter(dispatchGroup); /** We cannot properly retrieve raw type images with the current authorization status. If the image is of type raw, we ignore it. */ if ([itemProvider hasItemConformingToTypeIdentifier:@"public.camera-raw-image"]) { NSException *exception = [NSException exceptionWithName:@"ImageIsTypeRaw" reason:[NSString stringWithFormat:@"Object is type raw. ItemProvider: %@", itemProvider.description] userInfo:nil]; // Log exception... dispatch_group_leave(dispatchGroup); continue; } if ([itemProvider canLoadObjectOfClass:UIImage.class]) { [itemProvider loadObjectOfClass:UIImage.class completionHandler: ^(__kindof id <NSItemProviderReading> _Nullable object, NSError *_Nullable error) { if ([object isKindOfClass:UIImage.class]) { NewPicture *picture = [[NewPicture alloc]initWithImage:object]; [picArray addObject:picture]; } if (error) { NSException *exception = [NSException exceptionWithName:@"CouldNotLoadImage" reason:[NSString stringWithFormat:@"Object is nil. UserInfo: %@", error.userInfo] userInfo:error.userInfo]; // Log exception... } dispatch_group_leave(dispatchGroup); }]; } } dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ picturesBlock(picArray); });
The most common error we see our users are getting is:
Code Block Object is nil. UserInfo: { NSLocalizedDescription = "Cannot load representation of type public.jpeg"; NSUnderlyingError = "Error Domain=NSCocoaErrorDomain Code=260 \"The file \U201cversion=1&uuid=*&mode=current.jpeg\U201d couldn\U2019t be opened because there is no such file.\" UserInfo={NSURL=file:///private/var/mobile/Containers/Shared/AppGroup/*/File%20Provider%20Storage/photospicker/version=1&uuid=*&mode=current.jpeg, NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/*/File Provider Storage/photospicker/version=1&uuid=***&mode=current.jpeg, NSUnderlyingError=0x283822970 {Error Domain=NSPOSIXErrorDomain Code=2 \"No such file or directory\"}}"; }
I'm having a really hard time understanding why this sometimes fails. I'd really appreciate it if someone could give me a hand with this.
I'm attaching the stack trace: