-
I currently have a React Native + Expo Go app, and I run a native build in Xcode. My original Podfile (Figure 1) works correctly and compiles without issues.
-
My team is trying to integrate our app into an iOS Custom Keyboard Extension. See example in figure 1. The original podfile compiles and works even with the keyboard extension added. However, the problems begin when I try to import the React module to KeyboardViewControl objective-C and header files.
- Imports:
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
- Build Error:
- I encountered build errors after importing some React headers and updating the Podfile to the structure shown in Figure 2.
- I have tried various Podfile configurations and imports, but I keep encountering different errors depending on the structure.
Figure 1: Sample keyboard extension:
Figure 2: Original Working podfile without extensions:
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods',
:deterministic_uuids => false
prepare_react_native_project!
target 'AppPrototype' do
use_expo_modules!
config = use_native_modules!
# changed re https://rnfirebase.io/#altering-cocoapods-to-use-frameworks
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
# use_frameworks! :linkage => :static
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
$RNFirebaseAsStaticFramework = true
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/..",
# Temporarily disable privacy file aggregation by default, until React
# Native 0.74.2 is released with fixes.
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] == 'true',
)
post_install do |installer|
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
:ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
)
# This is necessary for Xcode 14, because it signs resource bundles by default
# when building for devices.
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end
post_integrate do |installer|
begin
expo_patch_react_imports!(installer)
rescue => e
Pod::UI.warn e
end
end
end
Figure 3: New podfile with extension target:
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods',
:deterministic_uuids => false
prepare_react_native_project!
target 'AppPrototype' do
use_expo_modules!
config = use_native_modules!
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
$RNFirebaseAsStaticFramework = true
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
:app_path => "#{Pod::Config.instance.installation_root}/..",
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] == 'true',
)
end
target 'SymbolGridExt_v1' do
use_expo_modules!
config = use_native_modules!
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
:app_path => "#{Pod::Config.instance.installation_root}/..",
)
pre_install do |installer|
installer.pod_targets.each do |pod|
if pod.name.include?('Firebase') || pod.name.include?('GoogleUtilities') || pod.name.include?('FirebaseCoreInternal') || pod.name.include?('FirebaseCore')
pod.target_definitions.each do |target_definition|
if target_definition.name == 'SymbolGridExt_v1'
target_definition.dependencies.delete_if { |dep| dep.name == pod.name }
end
end
end
end
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'SymbolGridExt_v1'
# Remove Firebase and Google utilities for SymbolGridExt_v1 target
target.dependencies.delete_if { |dependency|
dependency.name.include?('Firebase') ||
dependency.name.include?('GoogleUtilities') ||
dependency.name.include?('FirebaseCoreInternal') ||
dependency.name.include?('FirebaseCore')
}
end
end
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['HEADER_SEARCH_PATHS'] ||= ['$(inherited)', '$(SRCROOT)/../node_modules/react-native/React/**', '$(SRCROOT)/../node_modules/react-native/ReactCommon/**']
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'RCT_ENABLE_INSPECTOR=1', 'RCT_REMOTE_PROFILE=1']
end
end
installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['HEADER_SEARCH_PATHS'] ||= ['$(inherited)', '$(SRCROOT)/../node_modules/react-native/React/**', '$(SRCROOT)/../node_modules/react-native/ReactCommon/**']
end
end
end