I have a function that returns an array of photos and videos from an iOS device's camera roll. The info is returned correctly, however, I'm also needing to return the path to the photo and video which I've been unable to do so far.
Here is the code I'm using. The photo and video path code is about 2/3 down this snippet starting with: "if (asset.mediaType == PHAssetMediaTypeImage)":
- (void) photos:(CDVInvokedUrlCommand*)command {
if (![self isNull:self.photosCommand]) {
[self failure:command withMessage:E_PHOTO_BUSY];
return;
}
self.photosCommand = command;
CDVPhotos* __weak weakSelf = self;
[self checkPermissionsOf:command andRun:^{
NSArray* collectionIds = [weakSelf argOf:command atIndex:0 withDefault:nil];
NSLog(@"photos: collectionIds=%@", collectionIds);
NSDictionary* options = [weakSelf argOf:command atIndex:1 withDefault:@{}];
int offset = [[weakSelf valueFrom:options
byKey:P_LIST_OFFSET
withDefault:@"0"] intValue];
int limit = [[weakSelf valueFrom:options
byKey:P_LIST_LIMIT
withDefault:@"0"] intValue];
NSTimeInterval interval = [[weakSelf valueFrom:options
byKey:P_LIST_INTERVAL
withDefault:@"30"] intValue];
interval = interval < 0 ? .03f : interval / 1000.0f;
PHFetchResult<PHAssetCollection*>* fetchResultAssetCollections
= collectionIds == nil || collectionIds.count == 0
? [weakSelf fetchCollections:@{}]
: [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:collectionIds
options:nil];
if (fetchResultAssetCollections == nil) {
weakSelf.photosCommand = nil;
[weakSelf failure:command withMessage:E_COLLECTION_MODE];
return;
}
int __block fetched = 0;
NSMutableArray<PHAsset*>* __block skippedAssets = [NSMutableArray array];
NSMutableArray<NSDictionary*>* __block result = [NSMutableArray array];
[fetchResultAssetCollections enumerateObjectsUsingBlock:
^(PHAssetCollection* _Nonnull assetCollection, NSUInteger idx, BOOL* _Nonnull stop) {
if ([weakSelf isNull:weakSelf.photosCommand]) {
*stop = YES;
return;
}
PHFetchOptions* fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.sortDescriptors = @[[NSSortDescriptor
sortDescriptorWithKey:@"creationDate"
ascending:YES]];
fetchOptions.predicate
= [NSPredicate predicateWithFormat:@"mediaType = %d OR mediaType = %d", PHAssetMediaTypeImage, PHAssetMediaTypeVideo];
PHFetchResult<PHAsset*>* fetchResultAssets =
[PHAsset fetchAssetsInAssetCollection:assetCollection options:fetchOptions];
[fetchResultAssets enumerateObjectsUsingBlock:
^(PHAsset* _Nonnull asset, NSUInteger idx, BOOL* _Nonnull stop) {
if ([weakSelf isNull:weakSelf.photosCommand]) {
*stop = YES;
return;
}
NSArray *resources = [PHAssetResource assetResourcesForAsset:asset];
NSString *filename = ((PHAssetResource*)resources[0]).originalFilename;
NSTextCheckingResult* match
= [weakSelf.extRegex
firstMatchInString:filename
options:0
range:NSMakeRange(0, filename.length)];
NSString* name = [filename substringWithRange:[match rangeAtIndex:1]];
NSString* ext = [[filename substringWithRange:[match rangeAtIndex:2]] uppercaseString];
NSString* type = weakSelf.extType[ext];
if (offset <= fetched) {
if (asset.mediaType == PHAssetMediaTypeImage)
{
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
NSURL *url = [info objectForKey:@"PHImageFileURLKey"];
// do what you want with it
}];
}
else if (asset.mediaType == PHAssetMediaTypeVideo)
{
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info)
{
if ([asset isKindOfClass:[AVURLAsset class]])
{
NSURL *url = [(AVURLAsset*)asset URL];
// do what you want with it
}
}];
}
NSMutableDictionary<NSString*, NSObject*>* assetItem
= [NSMutableDictionary dictionaryWithObjectsAndKeys:
asset.localIdentifier, P_ID,
name, P_NAME,
type, P_TYPE,
[weakSelf.dateFormat stringFromDate:asset.creationDate], P_DATE,
@((long) (asset.creationDate.timeIntervalSince1970 * 1000)), P_TS,
@(asset.pixelWidth), P_WIDTH,
@(asset.pixelHeight), P_HEIGHT,
nil];
if (![weakSelf isNull:asset.location]) {
CLLocationCoordinate2D coord = asset.location.coordinate;
[assetItem setValue:@(coord.latitude) forKey:P_LAT];
[assetItem setValue:@(coord.longitude) forKey:P_LON];
}
[result addObject:assetItem];
if (limit > 0 && result.count >= limit) {
[weakSelf partial:command withArray:result];
[result removeAllObjects];
[NSThread sleepForTimeInterval:interval];
}
}
++fetched;
}];
}];
[skippedAssets enumerateObjectsUsingBlock:^(PHAsset* _Nonnull asset, NSUInteger idx, BOOL* _Nonnull stop) {
NSLog(@"skipped asset %lu: id=%@; name=%@, type=%ld-%ld; size=%lux%lu;",
idx, asset.localIdentifier, [weakSelf getFilenameForAsset:asset],
(long)asset.mediaType, (long)asset.mediaSubtypes,
(unsigned long)asset.pixelWidth, asset.pixelHeight);
}];
weakSelf.photosCommand = nil;
[weakSelf success:command withArray:result];
}];
}
Is there an easier way to get the path of these photos and videos? Is there a single path that can be used to the Camera Roll that would be supported across different iPhone's?