Skip to content

Commit 6fbbb37

Browse files
committed
Merge branch 'master' of github.com:marcshilling/react-native-image-picker
2 parents 264fbeb + 1166020 commit 6fbbb37

File tree

2 files changed

+93
-19
lines changed

2 files changed

+93
-19
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ storageOptions | OK | OK | If this key is provided, the image will get saved in
190190
storageOptions.skipBackup | OK | - | If true, the photo will NOT be backed up to iCloud
191191
storageOptions.path | OK | - | If set, will save image at /Documents/[path] rather than the root
192192
storageOptions.cameraRoll | OK | - | If true, the cropped photo will be saved to the iOS Camera Roll.
193-
storageOptions.waitUntilSaved | OK | - | If true, will delay the response callback until after the photo/video was saved to the Camera Roll.
193+
storageOptions.waitUntilSaved | OK | - | If true, will delay the response callback until after the photo/video was saved to the Camera Roll. If the photo or video was just taken, then the file name and timestamp fields are only provided in the response object when this is true.
194194

195195
### The Response Object
196196

@@ -206,9 +206,9 @@ width | OK | OK | Image dimensions
206206
height | OK | OK | Image dimensions
207207
fileSize | OK | OK | The file size (photos only)
208208
type | - | OK | The file type (photos only)
209-
fileName | - | OK | The file name (photos only)
209+
fileName | OK (photos and videos) | OK (photos) | The file name
210210
path | - | OK | The file path
211-
latitude | - | OK | Latitude metadata, if available
212-
longitude | - | OK | Longitude metadata, if available
213-
timestamp | - | OK | Timestamp metadata, if available, in ISO8601 UTC format
214-
originalRotation | - | OK | Rotation degrees (photos only) *See [#109](/../../issues/199)*
211+
latitude | OK | OK | Latitude metadata, if available
212+
longitude | OK | OK | Longitude metadata, if available
213+
timestamp | OK | OK | Timestamp metadata, if available, in ISO8601 UTC format
214+
originalRotation | - | OK | Rotation degrees (photos only) *See [#109](/../../issues/199)*

ios/ImagePickerManager.m

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,30 @@ - (void)launchImagePicker:(RNImagePickerTarget)target
219219
}
220220
}
221221

222+
- (NSString * _Nullable)originalFilenameForAsset:(PHAsset * _Nullable)asset assetType:(PHAssetResourceType)type {
223+
if (!asset) { return nil; }
224+
225+
PHAssetResource *originalResource;
226+
// Get the underlying resources for the PHAsset (PhotoKit)
227+
NSArray<PHAssetResource *> *pickedAssetResources = [PHAssetResource assetResourcesForAsset:asset];
228+
229+
// Find the original resource (underlying image) for the asset, which has the desired filename
230+
for (PHAssetResource *resource in pickedAssetResources) {
231+
if (resource.type == type) {
232+
originalResource = resource;
233+
}
234+
}
235+
236+
return originalResource.originalFilename;
237+
}
238+
222239
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
223240
{
224241
dispatch_block_t dismissCompletionBlock = ^{
225242

226243
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
227244
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
228245

229-
230246
NSString *fileName;
231247
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
232248
NSString *tempFileName = [[NSUUID UUID] UUIDString];
@@ -284,6 +300,19 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
284300
image = [info objectForKey:UIImagePickerControllerOriginalImage];
285301
}
286302

303+
if (imageURL) {
304+
PHAsset *pickedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil].lastObject;
305+
NSString *originalFilename = [self originalFilenameForAsset:pickedAsset assetType:PHAssetResourceTypePhoto];
306+
self.response[@"fileName"] = originalFilename ?: [NSNull null];
307+
if (pickedAsset.location) {
308+
self.response[@"latitude"] = @(pickedAsset.location.coordinate.latitude);
309+
self.response[@"longitude"] = @(pickedAsset.location.coordinate.longitude);
310+
}
311+
if (pickedAsset.creationDate) {
312+
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:pickedAsset.creationDate];
313+
}
314+
}
315+
287316
// GIFs break when resized, so we handle them differently
288317
if (imageURL && [[imageURL absoluteString] rangeOfString:@"ext=GIF"].location != NSNotFound) {
289318
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
@@ -374,10 +403,27 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
374403

375404
NSDictionary *storageOptions = [self.options objectForKey:@"storageOptions"];
376405
if (storageOptions && [[storageOptions objectForKey:@"cameraRoll"] boolValue] == YES && self.picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
406+
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
377407
if ([[storageOptions objectForKey:@"waitUntilSaved"] boolValue]) {
378-
UIImageWriteToSavedPhotosAlbum(image, self, @selector(savedImage : hasBeenSavedInPhotoAlbumWithError : usingContextInfo :), nil);
408+
[library writeImageToSavedPhotosAlbum:image.CGImage metadata:[info valueForKey:UIImagePickerControllerMediaMetadata] completionBlock:^(NSURL *assetURL, NSError *error) {
409+
if (error) {
410+
NSLog(@"Error while saving picture into photo album");
411+
} else {
412+
// when the image has been saved in the photo album
413+
if (assetURL) {
414+
PHAsset *capturedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[assetURL] options:nil].lastObject;
415+
NSString *originalFilename = [self originalFilenameForAsset:capturedAsset assetType:PHAssetResourceTypePhoto];
416+
self.response[@"fileName"] = originalFilename ?: [NSNull null];
417+
// This implementation will never have a location for the captured image, it needs to be added manually with CoreLocation code here.
418+
if (capturedAsset.creationDate) {
419+
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:capturedAsset.creationDate];
420+
}
421+
}
422+
self.callback(@[self.response]);
423+
}
424+
}];
379425
} else {
380-
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
426+
[library writeImageToSavedPhotosAlbum:image.CGImage metadata:[info valueForKey:UIImagePickerControllerMediaMetadata] completionBlock:nil];
381427
}
382428
}
383429
}
@@ -386,6 +432,19 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
386432
NSURL *videoURL = info[UIImagePickerControllerMediaURL];
387433
NSURL *videoDestinationURL = [NSURL fileURLWithPath:path];
388434

435+
if (videoRefURL) {
436+
PHAsset *pickedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[videoRefURL] options:nil].lastObject;
437+
NSString *originalFilename = [self originalFilenameForAsset:pickedAsset assetType:PHAssetResourceTypeVideo];
438+
self.response[@"fileName"] = originalFilename ?: [NSNull null];
439+
if (pickedAsset.location) {
440+
self.response[@"latitude"] = @(pickedAsset.location.coordinate.latitude);
441+
self.response[@"longitude"] = @(pickedAsset.location.coordinate.longitude);
442+
}
443+
if (pickedAsset.creationDate) {
444+
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:pickedAsset.creationDate];
445+
}
446+
}
447+
389448
if ([videoURL.URLByResolvingSymlinksInPath.path isEqualToString:videoDestinationURL.URLByResolvingSymlinksInPath.path] == NO) {
390449
NSFileManager *fileManager = [NSFileManager defaultManager];
391450

@@ -417,6 +476,16 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
417476
} else {
418477
NSLog(@"Save video succeed.");
419478
if ([[storageOptions objectForKey:@"waitUntilSaved"] boolValue]) {
479+
if (assetURL) {
480+
PHAsset *capturedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[assetURL] options:nil].lastObject;
481+
NSString *originalFilename = [self originalFilenameForAsset:capturedAsset assetType:PHAssetResourceTypeVideo];
482+
self.response[@"fileName"] = originalFilename ?: [NSNull null];
483+
// This implementation will never have a location for the captured image, it needs to be added manually with CoreLocation code here.
484+
if (capturedAsset.creationDate) {
485+
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:capturedAsset.creationDate];
486+
}
487+
}
488+
420489
self.callback(@[self.response]);
421490
}
422491
}
@@ -458,16 +527,6 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
458527
});
459528
}
460529

461-
- (void)savedImage:(UIImage *)image hasBeenSavedInPhotoAlbumWithError:(NSError *)error usingContextInfo:(void*)ctxInfo
462-
{
463-
if (error) {
464-
NSLog(@"Error while saving picture into photo album");
465-
} else {
466-
// when the image has been saved in the photo album
467-
self.callback(@[self.response]);
468-
}
469-
}
470-
471530
#pragma mark - Helpers
472531

473532
- (void)checkCameraPermissions:(void(^)(BOOL granted))callback
@@ -630,4 +689,19 @@ - (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
630689
}
631690
}
632691

692+
#pragma mark - Class Methods
693+
694+
+ (NSDateFormatter * _Nonnull)ISO8601DateFormatter {
695+
static NSDateFormatter *ISO8601DateFormatter;
696+
static dispatch_once_t onceToken;
697+
dispatch_once(&onceToken, ^{
698+
ISO8601DateFormatter = [[NSDateFormatter alloc] init];
699+
NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
700+
ISO8601DateFormatter.locale = enUSPOSIXLocale;
701+
ISO8601DateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
702+
ISO8601DateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZZZZZ";
703+
});
704+
return ISO8601DateFormatter;
705+
}
706+
633707
@end

0 commit comments

Comments
 (0)