Remotely install react native pods ios podFile instead of require_relative - react-native

I want to use React Native Pods into one of my iOS Apps which is built using Swift. I have bundled my React Native components into ios-main.jsbundle. I am consuming the routes as shown below:
class ContentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func loadView() {
loadReactNativeView()
}
func loadReactNativeView() {
let jsCodeLocation = Bundle.main.url(forResource: "main-ios", withExtension: "jsbundle")!
let rootView = RCTRootView(
bundleURL: jsCodeLocation,
moduleName: "YourApp",
initialProperties: nil,
launchOptions: nil
)
self.view = rootView
}
}
and in order to use React, I have done pod installation with my podFile something like as shown below:
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/#react-native-community/cli-platform-ios/native_modules'
platform :ios, '13.0'
target 'yourreactnativeapp' do
use_react_native!
end
This works fine but here's the problem, my ios file is a root git directory and so I can't go one level up... again to perform pod installation, even if I place the files into my ios directory that would mean uploading entire node modules, which doesn't seem like a good solution, is there a way that I could use something other than require_relative to install React Native pod dependencies remotely from somewhere? I am okay with uploading node modules into another git repo and then fetching it from there.

Related

How to create podspec file for a React Native Library

I am writing my components in React Native using react-native cli and am damn frustrated and confused about configuring it to be consumed as a library. Here's how the react native folder structure looks like:
src
ios
build
projectName.xcodeproj
projectName.xcodeworkspace
PodFile
PodFile.lock
...
android
index.js
...
when I open the xcode and build the project everything works fine as expected, now here's the thing. My React Native code sits into a git repository (Repo-A) which is different from an ios-repository (Repo-B) which contains collection of lot of independent pods.
All I want is to configure my project (Repo-A) MyApp to be consumed by Repo-B. I want to understand two syntax:
How do I add podSpec file in my Repo-A so that it points to ios directory so that it could be picked up by other repositories (in this case Repo-B).
In order to include the podfile in a specific repo (Repo-B in this case), all I need to do is the below snippet or something else? [Also how does podFile get access to these private repositories?]
Here's how I would like to consume it:
pod 'MyApp', :git => 'https://github.com/<username>/my-app', :branch => 'main'
Someone please help me understanding how can I achieve this? (Connecting the podFiles).
Additionally, one more thing I would like to know is how the versioning works? Like lets say I make some updates to my codebase, if I push it all to main and rebuild the Repo-B would that be sufficient to update changes in app or should I be using tags and create podSpec for each changes?
I can answer at least part of your question:
In Repo-A, create a podspec file with the same name as your library: my-library-name.podspec. Add this code:
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
folly_version = '2021.06.28.00-v2'
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
Pod::Spec.new do |s|
s.name = "my-library-name"
s.version = package["version"]
s.summary = package["description"]
s.homepage = package["homepage"]
s.license = package["license"]
s.authors = package["author"]
s.platforms = { :ios => "10.0" }
s.source = { :git => "https://github.com/<username>/my-app", :tag => "#{s.version}" }
s.source_files = ['ios/']
s.dependency "React-Core"
# Don't install the dependencies when we run `pod install` in the old architecture.
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
s.pod_target_xcconfig = {
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}
s.dependency "React-Codegen"
s.dependency "RCT-Folly", folly_version
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
end
end
The s.source_files points to the ios directory so that it can be referenced by other repositories.
Documentation on sourcing other repos in podspec: https://guides.cocoapods.org/syntax/podspec.html#source

Dynamically link packages based on product flavor to support GMS & HMS with one code base

In order for my application to be approved and visible on both of Google PlayStore and Huawei App Gallery, I am currently maintaining two different branches:
Google branch which has react-native-maps installed but no HMS packages.
Huawei branch which has HMS maps installed but not react-native-maps.
I'm aware of the HMS+GMS approach, but from my experience having a module like react-native-maps that relies heavily on GMS made my app hidden from pure HMS devices, even though my app had ways to check and never navigate to screens that rely on GMS.
Both branches have the same code on the JavaScript side except one file which is used to display the map, this file imports from react-native-maps on GMS phones, and from react-native-hms-map for Huawei phones.
My question is: is there a way to dynamically exclude some files and packages in build time based on the product flavor so that I can use one codebase and just ignore some file when building the APK.
Solution:
Managed to come up with a solution that got my app approved and fully visible on app stores through disabling auto linking for react native maps and manually linking it based on the product flavor.
(Code might not be the cleanest but it's behaving as expected, so any cleanup suggestions would be appreciated)
Steps:
1. Disable manual linking for react-native-maps on android
By creating a file named react-native.config.js in the root directory of the project, and added the following
module.exports = {
dependencies: {
"react-native-maps": {
platforms: {
android: null,
}
}
}
}
2. Added product flavors for Google and Huawei
By adding the following to android/app/build.gradle
...
...
android{
...
...
flavorDimensions "provider"
productFlavors {
google {
dimension "provider"
}
huawei {
dimension "provider"
}
}
...
...
}
...
...
3. Added the following to the same android/app/build.gradle file
...
...
dependencies {
...
...
huaweiImplementation 'com.huawei.hms:location:4.0.2.300'
huaweiImplementation 'com.huawei.hms:hwid:4.0.1.300'
googleImplementation project(':react-native-maps')
...
...
}
...
...
4. Added the following into android/settings.gradle
include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')
5. Created 2 folders inside android/app/src
folders named: huawei and google with the following structure
6. added a java file inside android/app/src/google/java/com/appname
MapPackageChecker.java
package com.appname;
import com.facebook.react.ReactPackage;
import com.airbnb.android.react.maps.MapsPackage;
public class MapPackageChecker {
public static ReactPackage getMapPackage() {
return new MapsPackage();
}
}
7. added a java file inside android/app/src/huawei/java/com/appname
MapPackageChecker.java
package com.appname;
import com.facebook.react.ReactPackage;
public class MapPackageChecker {
public static ReactPackage getMapPackage() {
return null;
}
}
8. added the following to android/app/src/main/java/com/appname/MainApplication.java
import static com.appname.MapPackageChecker.getMapPackage;
...
...
#Override
protected List<ReactPackage> getPackages() {
#SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
//start of new lines
if(BuildConfig.FLAVOR.equals("google")){
packages.add(getMapPackage());
}
//end of new lines
return packages;
}
...
...
9. Access flavor name from react native code
I decided to use react-native-build-config for this purpose
Example for navigation component:
import googleMapScreen from "./googleMapScreen.js"; //relies on gms maps
import huaweiMapScreen from "./huaweiMapScreen.js"; //relies on hms maps
import BuildConfig from 'react-native-build-config';
const flavor = BuildConfig.FLAVOR
...
...
<Stack.Screen
name="MapScreen"
component={flavor === "huawei" ? huaweiMapScreen : googleMapScreen}
/>
...
...
10. After adding product flavors, we need to make some changes to our commands
yarn react-native run-android
becomes: yarn react-native run-android --variant=huaweiDebug
or: yarn react-native run-android --variant=googleDebug
./gradlew assembleRelease
becomes: ./gradlew assembleHuaweiRelease
or: ./gradlew assembleGoogleRelease
11. For convenience we can add the following to package.json scripts
"scripts":{
"run-huawei": "yarn react-native run-android --variant=huaweiDebug",
"run-google": "yarn react-native run-android --variant=googleDebug",
}
First of all, Huawei does support react-native-maps. Please check here: https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides-V1/integrating-sdk-0000001050034173-V1
When HMS+GMS is the preferred solution, in the code the APP needs to decide whether to use HMS or GMS based on the availability of HMS and GMS services on the device.
. How to decide whether to use HMS or GMS :
Check that GMS is available
There are also some links for your reference:
React Native Application Detect device support GMS or HMS: https://forums.developer.huawei.com/forumPortal/en/topic/0201200045194610058?fid=0101187876626530001
Choice SDK - an open-source GMS-HMS wrapper: https://forums.developer.huawei.com/forumPortal/en/topic/0201555879126330259?fid=0101187876626530001
You may refer to this.
It's configured in hereļ¼š
And run the following command:

React-native-fast-image is not working on ios14 OS xocde beta [duplicate]

I've upgraded my iPhone device to iOS 14 beta and Xcode 12 beta. Then all Image/Fast Image on my React Native project can not show (which work well on previous iOS 13 and Xcode 11.5).
This is a problem with react-native <= 0.63.1 and iOS 14
This issue is fixed and merged to react native latest version. But if you want to fix your project now or you are using under 0.63.2 versions, there is a solution. (Thanks to https://bityl.co/3ksz)
FIRST SOLUTION : If you can update React Native
Update react-native to v0.63.2 or superior
Its was fixed in this release : https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#v0632
SECOND SOLUTION : If you can't update React Native
OPEN THE FILE FROM :
node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
EDIT SOURCE
From
#pragma mark - CALayerDelegate
- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}
To
#pragma mark - CALayerDelegate
- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
} else {
[super displayLayer:layer];
}
}
MAKE PATCH
npx patch-package react-native
MAKE PATCH FILES TRACKED FOR GIT
git add patches/*
ADD PACKAGE SCRIPT FOR AUTO APPLYING PATCHES
package.json
"scripts": {
...
"postinstall": "patch-package",
}
It will patch from all patch files whenever you install packages.
Try using react-native+0.63.0.patch as suggested here https://github.com/facebook/react-native/issues/29279#issuecomment-657201709
diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
## -272,6 +272,9 ## - (void)displayDidRefresh:(CADisplayLink *)displayLink
- (void)displayLayer:(CALayer *)layer
{
+ if (!_currentFrame) {
+ _currentFrame = self.image;
+ }
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
## -0,0 +1 ##
+export RCT_METRO_PORT=8081
To use the patch
run npm i -g patch-package
Make a new folder called patches
Make a new file called react-native+0.63.0.patch inside that folder
Add the source code above
run patch-package on the root of the project
Update to React Native 0.63.2. Fixed in https://github.com/facebook/react-native/commit/b6ded7261544c703e82e8dbfa442dad4b201d428
This is related to https://github.com/SDWebImage/SDWebImage/issues/3040.
Simply update SDWebImage in your Podfile or remove Podfile.lock and re-install.
if you are not running latest react-native version ( > 0.63.2) or not planning to upgrade to latest version of react-native. Then you can be your temp fix, try changing node_modules as below
Xcode 12 fix for IOS
I am using React Native v0.60.6 with React Native Fast Image v8.1.5.
Upgrading SDWebImage with pod update SDWebImage worked for me.
More specifically, I went from SDWebImage v5.8.1 to v5.9.2.
Xcode 12 builds seems to have issue, to fix i go to
node_modules > react-native > Libraries > Images >
RCTUIImageViewAnimated.m
And search for if (_currentFrame)
add else block to the if block as seen below code
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
} else {
[super displayLayer:layer];
}
I wouldn't recommend modifying node_modules. Following worked for me:
npm install --save react-native-fix-image
npx react-native-fix-image
rebuild project
My version information is as follows,
"react-native": "0.61.5",
"react-native-fast-image": "^7.0.2"
This worked for the pictures I show using FastImage.
pod repo remove trunk
pod update SDWebImage
For using the Image component that comes with react-native, you need to modify the source code. In the file node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m, modify the - (void)displayLayer:(CALayer *)layer method It can be as follows:
-(void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
} else {// Fix the bug that react-native 0.61.5 does not show pictures on xcode12
[super displayLayer:layer];
}
}
Here is the discussion for FastImage in github
Here is the discussion for react-native in github
It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.
//path
node_modules > react-native > Libraries > Images >
RCTUIImageViewAnimated.m
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
} else {
[super displayLayer:layer];
}
None of the previous answers worked for me.
I solved it by removing ios/Pods directory, then running pod install.
So:
cd ios
rm -rf Pods
pod install

Invariant Violation: requireNativeComponent: "RNCWebView" was not found in the UIManager

Hello friends i got this error after linking react-native-webview to my project
Invariant Violation: requireNativeComponent: "RNCWebView" was not found in the UIManager.
This error is located at:
in RNCWebView (at WebView.android.js:250)
in RCTView (at WebView.android.js:253)
in WebView (at App.js:7)
in App (at renderApplication.js:45)
in RCTView (at AppContainer.js:109)
in RCTView (at AppContainer.js:135)
in AppContainer (at renderApplication.js:39)
And there is my code
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
return (
<WebView
originWhitelist={['*']}
source={{ html: '<h1>Hello world</h1>' }}
/>
);
}
}
Error Image in my android
run react-native link react-native-webview
check: https://github.com/react-native-community/react-native-webview/issues/140
With React Native 0.60+, no need to add anything to the podfile.
Try again cd ios && pod install
If it doesn't help, try restarting the simulator and rebuilding the app.
Restarting Xcode is also a good idea.
You could optionally clean the build Folder in XCode
Try these steps.
Delete pods folder and podfile.lock
npm uninstall react-native-webview
npm i react-native-webview
cd ios
pod install
(npx) react-native run-ios
Reset cache
I had the same issue. Try Add this line to your podfile :-
pod 'react-native-webview', :path => PROJECT_PATH + 'react-native-webview'
then go to ios folder cd ios and install pods pod install
It has resolved this problem for me.
Make sure you did:
npx pod-install
npx react-native run-ios
After installing the package you. need to update pods and then run the project again.
my solution for this problem was the following:
Android
1 add this in your android/settings.gradle
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
2 add this in your android/app/build.gradle
dependencies {
implementation project(':react-native-webview')
....
3 in your MainApplication.java:
import com.reactnativecommunity.webview.RNCWebViewPackage;//add this import
....
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
#Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
#Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNCWebViewPackage(),//add line
....
IOS
1 add the following line in your ios/Podfile and then open your terminal, go to your project ios folder and run pod install
...
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
...
I had the same issue before , I tried this:
pod 'react-native-webview', :path => PROJECT_PATH + 'react-native-webview'
I update webView to the latest (11.18.1) and it was fixed without any additional linking steps.
I have done below steps:
1. cd ios
2. rm Podfile.lock
3. pod install
This installed the missing library i.e. react-native-webview and added below line to Podfile file.
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
environment which I am working on:
"react": "16.9.0",
"react-native": "0.61.5"
Follow these simple steps worked for me:
Rebuild the App. Run:
npx react-native run-android
Run:
react-native link react-native-webview
Check if RNCWebViewPackage is imported in MainApplication.java file, which looks something like this:
import com.reactnativecommunity.webview.RNCWebViewPackage;
Note: I'm using react-native#0.64.2.
There is no need to add anything or use the link for React Native 0.60+.
In my case, which was android, I simply build the project again using:
$ npm run android
Have you tried to link manually?
Go to ../node_modules/react-native-webview/ios and drag and drop the RNCWebView.xcodeproj to Libraries folder on Xcode, right after, Go to Build Phases tab (on Xcode) in the section "Link binary With libraries" add the libRNCWebView.a (inside Libraries/RNCWebView.xcodeproj/Products). Try to build and run
try to re-build your project after installation and link of webview package (npx react-native run-android)

AFNetworking pod install use of unresolved identifier methods

I install Mixpanel to my project and AFNetworking doesn't work anymore and in all methods show me this error:
Use of unresolved identifier 'AFHTTPRequestOperationManager'
But Xcode have link to the class in the method, I tried pod install, pod update, clean the project and it doesn't work
In PodFile:
target 'My Project' do
pod 'AFNetworking'
pod 'Mixpanel'
end
target 'Mi ProjectTests' do
end
In Bridging-Header:
#import <AFNetworking.h>
#import <Mixpanel/Mixpanel.h>
and the last error show is:
ld: framework not found -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
To AFNetworking 3.0 version:
let manager = AFHTTPSessionManager()
To solve the last error go to Build Settings, Other Linker Flags and remove all except $(inherited)
I had the same problem, after I update pod to the latest version of AFNetworking. There wasn't a AFHTTPRequestOperationManager anymore, so try to call this:
let manager = AFHTTPSessionManager()
Upload task with progress, in swift 3.0 like this:
let request = URLRequest(url: URL(string: "http://example.com/your/url")!)
manager.uploadTask(with: request, from: userData, progress: { (progress: Progress) in
// progress catching
}) { (response: URLResponse, object: Any?, error: Error?) in
// work with response
}