Skip to content

Commit ed6a082

Browse files
authored
fix(ios): Instagram singleShare iOS crash (#1667)
* Fix ig single share crash by adding missing permissions request * Update docs
1 parent 431ff10 commit ed6a082

File tree

2 files changed

+63
-20
lines changed

2 files changed

+63
-20
lines changed

ios/InstagramShare.m

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ @implementation InstagramShare
1414
- (void)shareSingle:(NSDictionary *)options
1515
reject:(RCTPromiseRejectBlock)reject
1616
resolve:(RCTPromiseResolveBlock)resolve {
17-
17+
1818
NSLog(@"Try open view");
19-
19+
2020
NSURL * shareURL;
2121
float videoDurationSeconds = 0.0f;
2222
NSString* url = options[@"url"];
@@ -25,13 +25,13 @@ - (void)shareSingle:(NSDictionary *)options
2525
AVURLAsset* videoAsset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
2626
CMTime videoDuration = videoAsset.duration;
2727
float videoDurationSeconds = CMTimeGetSeconds(videoDuration);
28-
28+
2929
NSLog(@"Video duration: %f seconds for file %@", videoDurationSeconds, videoAsset.URL.absoluteString);
3030
} else {
3131
//this will send message directly to instagram DM with plain text
3232
shareURL = [NSURL URLWithString:[NSString stringWithFormat:@"instagram://sharesheet?text=%@", options[@"message"]]];
3333
}
34-
34+
3535
if (shareURL) {
3636
NSLog(@"url is already available, no need to do anything");
3737
} else if (videoDurationSeconds <= 60.0f) {
@@ -42,30 +42,30 @@ - (void)shareSingle:(NSDictionary *)options
4242
} else {
4343
shareURL = [NSURL URLWithString:@"instagram://camera"];
4444
}
45-
45+
4646
if ([[UIApplication sharedApplication] canOpenURL: shareURL]) {
4747
[[UIApplication sharedApplication] openURL:shareURL options:@{} completionHandler:nil];
4848
resolve(@[@true, @""]);
4949
} else {
5050
// Cannot open instagram
5151
NSString *stringURL = @"https://itunes.apple.com/app/instagram/id389801252";
5252
NSURL *url = [NSURL URLWithString:stringURL];
53-
53+
5454
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {}];
55-
55+
5656
NSString *errorMessage = @"Not installed";
5757
NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedString(errorMessage, nil)};
5858
NSError *error = [NSError errorWithDomain:@"com.rnshare" code:1 userInfo:userInfo];
59-
59+
6060
NSLog(@"%@", errorMessage);
6161
reject(@"com.rnshare",@"Not installed",error);
62-
}
62+
}
6363
}
6464

6565
- (void)shareSingleImage:(NSDictionary *)options
6666
reject:(RCTPromiseRejectBlock)reject
6767
resolve:(RCTPromiseResolveBlock)resolve {
68-
68+
6969
UIImage *image;
7070
NSURL *imageURL = [RCTConvert NSURL:options[@"url"]];
7171
if (imageURL) {
@@ -92,22 +92,45 @@ - (void)shareSingleImage:(NSDictionary *)options
9292
-(void)savePictureAndOpenInstagram:(UIImage *)base64Image
9393
reject:(RCTPromiseRejectBlock)reject
9494
resolve:(RCTPromiseResolveBlock)resolve {
95-
95+
96+
// Check for photo library permissions
97+
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
98+
if (status == PHAuthorizationStatusNotDetermined) {
99+
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus newStatus) {
100+
dispatch_async(dispatch_get_main_queue(), ^{
101+
if (newStatus == PHAuthorizationStatusAuthorized) {
102+
[self savePictureAndOpenInstagram:base64Image reject:reject resolve:resolve];
103+
} else {
104+
if (reject != NULL) {
105+
reject(@"com.rnshare", @"Photo library access denied by user", nil);
106+
}
107+
}
108+
});
109+
}];
110+
return;
111+
} else if (status != PHAuthorizationStatusAuthorized) {
112+
113+
if (reject != NULL) {
114+
reject(@"com.rnshare", @"Photo library access not authorized", nil);
115+
}
116+
return;
117+
}
118+
96119
NSURL *URL = [self fileURLWithTemporaryImageData:UIImageJPEGRepresentation(base64Image, 0.9)];
97120
__block PHAssetChangeRequest *_mChangeRequest = nil;
98121
__block PHObjectPlaceholder *placeholder;
99-
122+
100123
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
101-
124+
102125
NSData *pngData = [NSData dataWithContentsOfURL:URL];
103126
UIImage *image = [UIImage imageWithData:pngData];
104127
_mChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
105128
placeholder = _mChangeRequest.placeholderForCreatedAsset;
106129
} completionHandler:^(BOOL success, NSError *error) {
107-
130+
108131
if (success) {
109132
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:@"instagram://library?LocalIdentifier=\%@", [placeholder localIdentifier]]];
110-
133+
111134
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
112135
if (@available(iOS 10.0, *)) {
113136
[[UIApplication sharedApplication] openURL:instagramURL options:@{} completionHandler:NULL];

website/docs/share-single.mdx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,28 @@ await Share.shareSingle({
142142
});
143143
```
144144

145-
**Note:** Your app's user must accept "All Photos" when prompted about photo permissions otherwise they may get a "Something went wrong" error.
146-
145+
**Warning!**
146+
To be able to use this feature, your app's user must accept "All Photos" when prompted about photo permissions,
147+
but first you need to add following permissions to your `Info.plist`:
148+
```xml
149+
<key>NSPhotoLibraryUsageDescription</key>
150+
<string>This app requires access to the photo library to save and share images on Instagram.</string>
151+
<key>NSPhotoLibraryAddUsageDescription</key>
152+
<string>This app requires access to the photo library to save and share images on Instagram.</string>
153+
```
154+
Or if you're using expo you can add them to `app.json` / `app.config.ts`:
155+
```typescript
156+
expo: {
157+
ios: {
158+
infoPlist: {
159+
NSPhotoLibraryUsageDescription:
160+
'This app requires access to the photo library to save and share images on Instagram',
161+
NSPhotoLibraryAddUsageDescription:
162+
'This app requires access to the photo library to save and share images on Instagram.',
163+
},
164+
}
165+
}
166+
```
147167

148168
### Share remote videos to Instagram
149169
Instagram tries to select **the very last file of the cameraroll** so you have to save videos to the cameraroll in case you want to share them to Instagram.
@@ -175,7 +195,7 @@ By default IG opens New post view with Camera View. There you can find also stor
175195
import Share from 'react-native-share';
176196

177197
const shareOptions = {
178-
url: 'instagram://camera',
198+
url: 'instagram://camera',
179199
social: Share.Social.INSTAGRAM
180200
};
181201

@@ -187,14 +207,14 @@ Share.shareSingle(shareOptions);
187207
import Share from 'react-native-share';
188208

189209
const shareOptions = {
190-
url: 'instagram://share',
210+
url: 'instagram://share',
191211
social: Share.Social.INSTAGRAM
192212
};
193213

194214
Share.shareSingle(shareOptions);
195215
```
196216

197-
URL patterns like `instagram://` can be used on Android, but works different then documented for IOS
217+
URL patterns like `instagram://` can be used on Android, but works different then documented for IOS
198218
https://developers.facebook.com/docs/instagram/sharing-to-feed/
199219

200220

0 commit comments

Comments
 (0)