Skip to content

Commit 818f799

Browse files
authored
feat: use own implementation to save cropped images on ios (#28)
1 parent 1db3d6b commit 818f799

File tree

6 files changed

+134
-9
lines changed

6 files changed

+134
-9
lines changed

ios/RNCFileSystem.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// RNFileSystem.h
3+
// RNCImageEditor
4+
//
5+
// Created by Dawid Urbaniak on 30/05/2019.
6+
// Copyright © 2019 Facebook. All rights reserved.
7+
//
8+
9+
#ifndef RNCFileSystem_h
10+
#define RNCFileSystem_h
11+
12+
#import <Foundation/Foundation.h>
13+
14+
@interface RNCFileSystem : NSObject
15+
16+
+ (BOOL)ensureDirExistsWithPath:(NSString *)path;
17+
+ (NSString *)generatePathInDirectory:(NSString *)directory withExtension:(NSString *)extension;
18+
+ (NSString *)cacheDirectoryPath;
19+
20+
@end
21+
22+
#endif /* RNCFileSystem_h */

ios/RNCFileSystem.m

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// RNFileSystem.m
3+
// RNCImageEditor
4+
//
5+
// Created by Dawid Urbaniak on 30/05/2019.
6+
// Copyright © 2019 Facebook. All rights reserved.
7+
//
8+
9+
#import "RNCFileSystem.h"
10+
11+
@implementation RNCFileSystem
12+
13+
+ (BOOL)ensureDirExistsWithPath:(NSString *)path
14+
{
15+
BOOL isDir = NO;
16+
NSError *error;
17+
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir];
18+
if (!(exists && isDir)) {
19+
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
20+
if (error) {
21+
return NO;
22+
}
23+
}
24+
return YES;
25+
}
26+
27+
+ (NSString *)generatePathInDirectory:(NSString *)directory withExtension:(NSString *)extension
28+
{
29+
NSString *fileName = [[[NSUUID UUID] UUIDString] stringByAppendingString:extension];
30+
[RNCFileSystem ensureDirExistsWithPath:directory];
31+
return [directory stringByAppendingPathComponent:fileName];
32+
}
33+
34+
+ (NSString *)cacheDirectoryPath
35+
{
36+
NSArray *array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
37+
return [array objectAtIndex:0];
38+
}
39+
40+
@end

ios/RNCImageEditor.m

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#import <React/RCTImageLoader.h>
1717
#import <React/RCTImageStoreManager.h>
18+
#import "RNCFileSystem.h"
19+
#import "RNCImageUtils.h"
1820
#if __has_include(<RCTImage/RCTImageUtils.h>)
1921
#import <RCTImage/RCTImageUtils.h>
2022
#else
@@ -28,7 +30,8 @@ @implementation RNCImageEditor
2830
@synthesize bridge = _bridge;
2931

3032
/**
31-
* Crops an image and adds the result to the image store.
33+
* Crops an image and saves the result to temporary file. Consider using
34+
* CameraRoll API or other third-party module to save it in gallery.
3235
*
3336
* @param imageRequest An image URL
3437
* @param cropData Dictionary with `offset`, `size` and `displaySize`.
@@ -69,15 +72,18 @@ @implementation RNCImageEditor
6972
}
7073

7174
// Store image
72-
[self->_bridge.imageStoreManager storeImage:croppedImage withBlock:^(NSString *croppedImageTag) {
73-
if (!croppedImageTag) {
74-
NSString *errorMessage = @"Error storing cropped image in RCTImageStoreManager";
75-
RCTLogWarn(@"%@", errorMessage);
76-
errorCallback(RCTErrorWithMessage(errorMessage));
75+
NSString *path = [RNCFileSystem generatePathInDirectory:[[RNCFileSystem cacheDirectoryPath] stringByAppendingPathComponent:@"ReactNative_cropped_image_"] withExtension:@".jpg"];
76+
77+
NSData *imageData = UIImageJPEGRepresentation(croppedImage, 1);
78+
NSError *writeError;
79+
NSString *uri = [RNCImageUtils writeImage:imageData toPath:path error:&writeError];
80+
81+
if (writeError != nil) {
82+
errorCallback(writeError);
7783
return;
78-
}
79-
successCallback(@[croppedImageTag]);
80-
}];
84+
}
85+
86+
successCallback(@[uri]);
8187
}];
8288
}
8389

ios/RNCImageEditor.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
1478DE2B22A0403F00D818FA /* RNCFileSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 1478DE2A22A0403F00D818FA /* RNCFileSystem.m */; };
11+
1478DE2E22A044E500D818FA /* RNCImageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1478DE2D22A044E500D818FA /* RNCImageUtils.m */; };
1012
B3E7B58A1CC2AC0600A0062D /* RNCImageEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNCImageEditor.m */; };
1113
/* End PBXBuildFile section */
1214

@@ -24,6 +26,10 @@
2426

2527
/* Begin PBXFileReference section */
2628
134814201AA4EA6300B7C361 /* libRNCImageEditor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCImageEditor.a; sourceTree = BUILT_PRODUCTS_DIR; };
29+
1478DE2A22A0403F00D818FA /* RNCFileSystem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCFileSystem.m; sourceTree = "<group>"; };
30+
1478DE2C22A0406800D818FA /* RNCFileSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCFileSystem.h; sourceTree = "<group>"; };
31+
1478DE2D22A044E500D818FA /* RNCImageUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCImageUtils.m; sourceTree = "<group>"; };
32+
1478DE2F22A0450800D818FA /* RNCImageUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCImageUtils.h; sourceTree = "<group>"; };
2733
B3E7B5881CC2AC0600A0062D /* RNCImageEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCImageEditor.h; sourceTree = "<group>"; };
2834
B3E7B5891CC2AC0600A0062D /* RNCImageEditor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCImageEditor.m; sourceTree = "<group>"; };
2935
/* End PBXFileReference section */
@@ -50,6 +56,10 @@
5056
58B511D21A9E6C8500147676 = {
5157
isa = PBXGroup;
5258
children = (
59+
1478DE2A22A0403F00D818FA /* RNCFileSystem.m */,
60+
1478DE2D22A044E500D818FA /* RNCImageUtils.m */,
61+
1478DE2F22A0450800D818FA /* RNCImageUtils.h */,
62+
1478DE2C22A0406800D818FA /* RNCFileSystem.h */,
5363
B3E7B5881CC2AC0600A0062D /* RNCImageEditor.h */,
5464
B3E7B5891CC2AC0600A0062D /* RNCImageEditor.m */,
5565
134814211AA4EA7D00B7C361 /* Products */,
@@ -112,6 +122,8 @@
112122
isa = PBXSourcesBuildPhase;
113123
buildActionMask = 2147483647;
114124
files = (
125+
1478DE2E22A044E500D818FA /* RNCImageUtils.m in Sources */,
126+
1478DE2B22A0403F00D818FA /* RNCFileSystem.m in Sources */,
115127
B3E7B58A1CC2AC0600A0062D /* RNCImageEditor.m in Sources */,
116128
);
117129
runOnlyForDeploymentPostprocessing = 0;

ios/RNCImageUtils.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// RNCImageUtils.h
3+
// RNCImageEditor
4+
//
5+
// Created by Dawid Urbaniak on 30/05/2019.
6+
// Copyright © 2019 Facebook. All rights reserved.
7+
//
8+
9+
#ifndef RNCImageUtils_h
10+
#define RNCImageUtils_h
11+
12+
#import <Foundation/Foundation.h>
13+
14+
@interface RNCImageUtils : NSObject
15+
16+
+ (NSString *)writeImage:(NSData *)image toPath:(NSString *)path error:(NSError **)error;
17+
18+
@end
19+
20+
21+
#endif /* RNCImageUtils_h */

ios/RNCImageUtils.m

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// RNCImageUtils.m
3+
// RNCImageEditor
4+
//
5+
// Created by Dawid Urbaniak on 30/05/2019.
6+
// Copyright © 2019 Facebook. All rights reserved.
7+
//
8+
9+
#import "RNCImageUtils.h"
10+
11+
@implementation RNCImageUtils
12+
13+
+ (id)writeImage:(id)image toPath:(id)path error:(NSError **)error
14+
{
15+
BOOL res = [image writeToFile:path atomically:YES];
16+
if (res == NO) {
17+
*error = [NSError errorWithDomain:@"org.reactnativecommunity.imageeditor.writeToFileError" code:101 userInfo:[NSDictionary dictionary]];
18+
return nil;
19+
}
20+
NSURL *fileURL = [NSURL fileURLWithPath:path];
21+
return [fileURL absoluteString];
22+
}
23+
24+
@end

0 commit comments

Comments
 (0)