Expensify / react-native-share-menu

A module for React Native that adds your app to the share menu of the device
MIT License
658 stars 240 forks source link

Build failing for IOS- 'sharedApplication' is unavailable: not available on iOS (App Extension) and openURL' is unavailable: not available on iOS (App Extension) #62

Closed RajatKumarChahar closed 4 years ago

RajatKumarChahar commented 4 years ago

First of all thanks for the awesome library.

I just updated the library to the latest version as now it also supports ios share extension and the documentation is well defined.

So, I checked the latest version on Android, and it's working fine without any hassle.

I tried to implement the same for IOS and followed each point mentioned in doc for ios. Now after doing everything, When I tried to build the ios app it failed.

'sharedApplication' is unavailable: not available on iOS (App Extension)
'openURL' is unavailable: not available on iOS (App Extension)

ENV

System:
    OS: macOS Mojave 10.14.5
    CPU: (4) x64 Intel(R) Core(TM) i5-5350U CPU @ 1.80GHz
    Memory: 255.73 MB / 8.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 10.16.0 - /usr/local/opt/node@10/bin/node
    Yarn: 1.12.3 - /usr/local/bin/yarn
    npm: 6.9.0 - /usr/local/opt/node@10/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
  IDEs:
    Xcode: 11.2.1/11B53 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: 0.61.5 => 0.61.5 
  npmGlobalPackages:
    react-native-cli: 2.0.1

podfile

platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'app' do
  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts.podspec"
  pod 'GoogleSignIn' # for RNGoogleSignin
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  target 'appTest' do
    inherit! :search_paths
    # Pods for testing
  end

  use_native_modules!
end

target 'ShareExtension' do
  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts.podspec"
  pod 'GoogleSignIn' # for RNGoogleSignin
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  pod 'RNShareMenu', :path => '../node_modules/react-native-share-menu'

  use_native_modules!

end

For ShareExtension I've set Require Only App-Extension Safe API in build settings to NO

AppDelegate.m

#import "AppDelegate.h"
#import <RNShareMenu/ShareMenuManager.h>

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)app
        openURL:(NSURL *)url
        options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [ShareMenuManager application:app openURL:url options:options];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end
Gustash commented 4 years ago

Hello @RajatKumarChahar, Require Only App-Extension Safe API isn't supposed to be set in the Share Extension target, but in every target inside the Pods project.

To fix this, add a post_install script anywhere in your Podfile like this:

post_install do |installer|
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
      end
    end
  end

Also, unless you're going to use the same native modules in your Share Extension as you do in your main app, I would recomment slimming down the ShareExtension target by only doing this:

target 'ShareExtension' do
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  pod 'RNShareMenu', :path => '../node_modules/react-native-share-menu'
end

This way you can manually link only the native modules you're going to use in your Share Extension, and keep the bundle size minimal.

RajatKumarChahar commented 4 years ago

Hello @Gustash, I've added post_install script. Now the error which was coming earlier is not coming but now

Apple Mach-O Linker error

is coming. I've cleaned the project and built the app again but it's still coming.

Gustash commented 4 years ago

Can you check if you have. -ObjC abd -lc++ in your Other Linker Flags on the Share Extension's Build Settings?

If not, add those and try again please.

RajatKumarChahar commented 4 years ago

Yes I've checked Other Linker Flags on the Share Extension's Build Settings and both -ObjC and -lc++ are present. To be more specific errors are

ld: warning: Could not find or use auto-linked library 'swiftDarwin'
ld: warning: Could not find or use auto-linked library 'swiftUIKit'
ld: warning: Could not find or use auto-linked library 'swiftCoreFoundation'
ld: warning: Could not find or use auto-linked library 'swiftCompatibility50'
ld: warning: Could not find or use auto-linked library 'swiftQuartzCore'
ld: warning: Could not find or use auto-linked library 'swiftCore'
ld: warning: Could not find or use auto-linked library 'swiftCoreGraphics'
ld: warning: Could not find or use auto-linked library 'swiftDispatch'
ld: warning: Could not find or use auto-linked library 'swiftObjectiveC'
ld: warning: Could not find or use auto-linked library 'swiftCoreImage'
ld: warning: Could not find or use auto-linked library 'swiftCompatibilityDynamicReplacements'
ld: warning: Could not find or use auto-linked library 'swiftMetal'
ld: warning: Could not find or use auto-linked library 'swiftFoundation'
ld: warning: Could not find or use auto-linked library 'swiftSwiftOnoneSupport'
Undefined symbols for architecture x86_64:
  "Foundation._convertErrorToNSError(Swift.Error) -> __C.NSError", referenced from:
      RNShareMenu.ShareMenuReactView.dismissExtension(Swift.String?) -> () in libRNShareMenu.a(ShareMenuReactView-B190363797C90082.o)
      reabstraction thunk helper from @escaping @callee_unowned @convention(block) (@unowned __C.NSString?, @unowned __C.NSString?, @unowned __C.NSError?) -> () to @escaping @callee_guaranteed (@guaranteed Swift.String?, @guaranteed Swift.String?, @guaranteed Swift.Error?) -> () in libRNShareMenu.a(ShareMenuReactView-B190363797C90082.o)
  "Foundation.URL.pathExtension.getter : Swift.String", referenced from:
      RNShareMenu.ShareMenuReactView.extractMimeType(from: Foundation.URL) -> Swift.String in libRNShareMenu.a(ShareMenuReactView-B190363797C90082.o)
      (extension in RNShareMenu):Foundation.URL.extractMimeType() -> Swift.String in libRNShareMenu.a(URL+Extensions.o)
  "Foundation.URL.absoluteString.getter : Swift.String", referenced from:
      closure #1 (__C.NSSecureCoding?, Swift.Error?) -> () in RNShareMenu.ShareMenuReactView.extractDataFromContext(context: __C.NSExtensionContext, withCallback: (Swift.String?, Swift.String?, __C.NSException?) -> ()) -> () in libRNShareMenu.a(ShareMenuReactView-B190363797C90082.o)
      closure #2 (__C.NSSecureCoding?, Swift.Error?) -> () in RNShareMenu.ShareMenuReactView.extractDataFromContext(context: __C.NSExtensionContext, withCallback: (Swift.String?, Swift.String?, __C.NSException?) -> ()) -> () in libRNShareMenu.a(ShareMenuReactView-B190363797C90082.o)
  "static Foundation.URL._unconditionallyBridgeFromObjectiveC(__C.NSURL?) -> Foundation.URL", referenced from:
      @objc static RNShareMenu.ShareMenuMessenger.share(application: __C.UIApplication, openUrl: Foundation.URL, options: [__C.UIApplicationOpenURLOptionsKey : Any]) -> () in libRNShareMenu.a(ShareMenuMessenger.o)
.
.
.
.
Gustash commented 4 years ago

Did you create a Bridging Header in your Share Extension, like the docs mention?

RajatKumarChahar commented 4 years ago

No, because it was mentioned for Custom IOS share View which was optional so I didn't.

Gustash commented 4 years ago

It shouldn't be necessary if you're not using a custom view, but can you please try it just as a sanity check?

RajatKumarChahar commented 4 years ago

I added the ShareExtension-BridgingHeader but it's still giving the same error

Gustash commented 4 years ago

Is it possible to get a repo that reproduces this problem? If you can't share your project, a stripped down version of it without any JS code and keys would be helpful

Gustash commented 4 years ago

@RajatKumarChahar what version of Xcode are you using btw?

RajatKumarChahar commented 4 years ago

@Gustash, I am using Xcode: 11.2.1

Gustash commented 4 years ago

@RajatKumarChahar okay, is it possible for you to share a project that reproduces that issue? I can't replicate it locally so I'd need to take a closer look at an affected project

RajatKumarChahar commented 4 years ago

@Gustash, Sure I'll create and share a repo that reproduces this issue.

codewithgigi commented 4 years ago

HI @Gustash I'm having the same issue. Did you find a solution for this?

Gustash commented 4 years ago

@jgardi which problem are you having? The first, or the second one?

RajatKumarChahar commented 4 years ago

I've found a workaround to fix the the Apple Mach-O Linker error problem. Create a swift file in project and when prompted to create a bridging file select yes. Re-build the project again and it builds successfully. For more info refer https://stackoverflow.com/questions/52536380/why-linker-link-static-libraries-with-errors-ios/61582562#61582562

Gustash commented 4 years ago

@RajatKumarChahar you mean creating a bridging header on the main app target?

RajatKumarChahar commented 4 years ago

@Gustash, Yes

Gustash commented 4 years ago

Thanks for letting me know. These instructions are already on the README. I will close this issue as it seems like it was just a step missed on the instructions