Library not linking with 0.41 versions of react-native - ios

I'm having issues linking libraries to a react-native project even after attempting to link manually multiple different times. I've gone through a ton of "praised" tutorials with no success.
I'm not an expert in Objective-C/iOS-native, so to isolate the issue I decided to create a HelloWorld Library and a HelloWorld react-native project.
Using:
react-native v0.41.2
react-native-cli v2.0.1
react-native-create-library v1.0.4
xcode v8.2.1
I did the following:
react-native-create-library Lib.
react-native init RNLibTest.
"Successfully linking" (Tried both manually and react-native link ...)
Here is the code:
RNLib
// ./ios/RNLib.h
#import <React/RCTBridgeModule.h>
#interface RNLib : NSObject <RCTBridgeModule>
#end
// ./ios/RNLib.m
#import "RNLib.h"
#implementation RNLib
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(helloWorld:(NSString *)world)
{
return [NSString stringWithFormat:#"hello %#", world];
}
#end
// ./index.js
import { NativeModules } from 'react-native';
const { RNLib } = NativeModules;
console.log(RNLib); // undefined
console.log(NativeModules); // Object: RNLib NOT included
export default RNLib;
HelloWorld / RNLibTest
// index.ios.js
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import RNLib from 'react-native-lib'; // I installed RNLib with npm and then "linked".
export default class RNLibTest extends Component {
componentDidMount() {
console.log(RNLib); // undefined
}
render() {
return (
<View>
<Text>Hello World</Text>
<Text>{
RNLib.helloWorld("world")
/* throws error "can't read property helloWorld of undefined" */
}</Text>
</View>
);
}
}
AppRegistry.registerComponent('RNLibTest', () => RNLibTest);
My questions:
If the code is not wrong, could it be the xcode project created by react-create-native-library somehow not working with newer versions of react-native?
Is anyone else having these issues? If so, what did you do to fix it?
If you haven't encountered this issue, are you using the latest version of react-native?
What version are you using of xcode, react-native-cli, etc...?
Did anyone have to downgrade to fix this issue?
UPDATE Feb/22/2017
There is a new release of react-native-create-library (v1.1.0) that supports v0.40+. I tried again and updated the code above, but I'm still seeing the same issue.
Here is a link to the GitHub issue. I also uploaded react-native-lib library and LibTest app to GitHub.

Not Sure Whether react-native-create-library support 0.41 RN But from the code i could say you need to import RCT*h files like <React/RCTBridgeModule.h>
Since this is single fine you can create a RNLib.h File in Xcode and check you would get compile time error
Thanks

I don't know what caused the issue but with react-native 0.42 out, I decided to try again.
Same code, same libraries, same everything BUT react-native 0.42, these were my results:
using react-native link => WORKED.
using manual installation => WORKED.
I'm not sure what happened in 0.41 but it is not happening in 0.42!

Related

Native UI Component throws Invariant Violation: tried to register two views with the same name FridgeCameraView

Trying to learn React Native custom Native UI Components.
// FridgeCameraViewManager.swift
import UIKit
#objc(FridgeCameraViewManager)
class FridgeCameraViewManager: RCTViewManager {
override func view() -> UIView! {
let label = UILabel()
label.text = "Swift Component"
label.textAlignment = .center
return label
}
#objc static override func requiresMainQueueSetup() -> Bool {
return false
}
}
.
// FridgeCameraViewManager.h
#import <Foundation/Foundation.h>
#import "React/RCTViewManager.h"
#interface RCT_EXTERN_MODULE(FridgeCameraViewManager, RCTViewManager)
#end
.
// FridgeCameraView.js
import {requireNativeComponent} from 'react-native';
const FridgeCameraView = requireNativeComponent('FridgeCameraView', null);
export default FridgeCameraView;
When I try to use FridgeCameraView component somewhere in App.js, it works only If I build & run the project using Xcode. Otherwise, using hot reload when changing something, I get "Invariant Violation: tried to register two views with the same name FridgeCameraView".
Somehow, the error went away when I installed react-router-native. I think there was a package conflict or something that I was missing. Hopefully, this will be a fix for the ones who encounter this error in the future. I'm still waiting for explanations if somebody knows what's behind this weird error.
(Not a solution, but still want to contribute)
TL;DR:
Just press R in terminal to refresh app
Auto hot-reload will register FridgeCameraView twice, reason unknown
For those of you who are wondering what's going on, we're learning the React Native - iOS Native Component and following the tutorial:
Swift in React Native - The Ultimate Guide Part 1: Modules
Swift in React Native - The Ultimate Guide Part 2: UI Components
And this is part 2 UI Components that went wrong. As React / React Native are changing fast, this scared resource on native component soon became outdated.
I accidentally need to reinstall my macOS & node_module, no luck in getting rid of the error. Installing another package doesn't solve the issue either.
I suspect that during React Native bridging in Swift -> Objective C -> React-JS, React Native will register our customized module FridgeCameraView twice; but will need expect in Objective C to dig deeper on this issue. Any contribution is welcomed!

Integrations of an iOS component in React Native

I am new to the development of React Native, I know iOS.
Just want to know about few points:
Can we add iOS (swift or objective C) code in a React Native App?
Can we add React Native Views into the existing iOS app?
I have googled and got the examples which point to that 2nd one is quite possible and Instagram did it in edit profile screen.
But I cannot find examples where it's a React Native app and we introduces swift or Objective-C code in between.
Please if anyone knows of any links or examples available for Case 1, please do let me know about it.
2nd question:
When we integrate react native with iOS, it will be through a bridge. Let's say I create an app in Swift, to get react native views in it, we have to go through 2 bridges, one converting Swift to Objective-C and then bridge between Objective-C to React Native. Is that correct? If yes will it be as fast as the native app?
Yes. You can do both of them
1.
https://facebook.github.io/react-native/docs/platform-specific-code.html
2.
https://codeburst.io/integrate-react-native-into-an-existing-app-ios-87c947a16044
https://facebook.github.io/react-native/docs/integration-with-existing-apps.html
Can we add iOS (swift or objective C) code in a React Native App
Yes, I was able to do so:-
I created a React Native project, compiled it and run it in the simulator.
Go to the iOS folder in directory structure in the project and open the .xcodeproj in xcode.
Create an objective c file (MyObjcClass) and make functions which you want to use in React.
MyObjcClass.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#interface MyObjcClass : NSObject <RCTBridgeModule>
#end
MyObjcClass.m
#import "MyObjcClass.h"
#implementation MyObjcClass
// tells react bridge to bridge our created class
RCT_EXPORT_MODULE()
- (NSDictionary *)constantsToExport {
return #{#"CreatedBy": #"Type any number and get Square"};
}
RCT_EXPORT_METHOD(squareNumber:(int)number getCallback:(RCTResponseSenderBlock)callback) {
callback(#[[NSNull null], [NSNumber numberWithInt:(number*number)]]);
}
Now we can call these methods in JS.
Below I will show how to call objective c in React.
App.js
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
// to import native code
import {NativeModules} from 'react-native';
var MyObjcClass = NativeModules.MyObjcClass;
export default class App extends React.Component {
state = {
number:0
};
squareMe(num) {
if (num == '') {
return;
}
MyObjcClass.squareNumber(parseInt(num), (error, number) => {
if (error) {
console.error(error);
} else {
this.setState({number: number});
}
})
}
render() {
return (
<View style={styles.container}>
<Text style={styles.spaceBetween}>Objective C inclusion</Text>
<TextInput placeholder="type a number ...." style={styles.input} onChangeText={(text) => this.squareMe(text)}/>
<ListItem placeName={this.state.number}></ListItem>
</View>
);
}
}
yes we can do
import {Platform} from 'react-native';
const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
console.log('Work around a change in behavior');
}
To bridge an iOS native module into React Native, you can follow along the official instructions: iOS Native Modules.
To paraphrase the important parts:
Open your .xcworkspace file in your ios folder to open XCode
Select File > New > File
Select header file
Name the header and select your project and its tests as the targets
// RCTCalendarModule.h
#import <React/RCTBridgeModule.h>
#interface RCTCalendarModule : NSObject <RCTBridgeModule>
#end
Select File > New > File
Select Objective-C file. Name it the same as the header but with .m instead of .h. Select your project and its tests and targets
// RCTCalendarModule.m
#import "RCTCalendarModule.h"
#implementation RCTCalendarModule
// To export a module named RCTCalendarModule
RCT_EXPORT_MODULE();
#end
In your React Native App or component, import NativeModules and use your new method
import {NativeModules, Button} from 'react-native';
const {CalendarModule} = NativeModules;
const onPress = () => {
CalendarModule.createCalendarEvent('testName', 'testLocation');
};
Note: You will need to keep rebuilding your ios app as you iterate (eg. run yarn ios after making a change to the .m or .h files)
For your second question, you can also add React Native into existing iOS apps. Follow these official instructions: Integration with Existing Apps.

I can't see any iOS Native Module in JS

I have some experience with React but I'm new to React Native.
I've played around for a while, but I got stuck when I tried to write a basic native module for iOS. I've tried with both Swift and Objective C. (I have some basic experience with Swift, but Objective C is completely new for me)
Some context:
The project is created with react-native-cli 2.0.1
I use XCode 9.1
Here is the .swift class
import Foundation
#objc(Something)
class Something: NSObject {
#objc
func printSomething() -> Void {
print("Something")
}
}
Here is the bridge file
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#interface RCT_EXTERN_MODULE(Something, NSObject)
RCT_EXTERN_METHOD(printSomething)
#end
And the Project-Brigding-Header.h
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import <React/RCTBridgeModule.h>
My App.js file
...
import { NativeModules } from 'react-native';
...
type Props = {};
export default class App extends Component<Props> {
componentDidMount() {
console.log('NativeModules: ', NativeModules);
}
...
}
Here is the problem. The output of console.log() says NativeModules is an empty object:
2018-02-22 18:19:04.590 [info][tid:com.facebook.react.JavaScript] 'NativeModules', {}
2018-02-22 18:19:04.589970+0200 velimo_app_rn[14748:400982] 'NativeModules', {}
I don't understand what I'm doing wrong. I've read pretty much everything I could find only related to the topic but I can't see what I do wrong.
If you have any suggestion, please let me know. Thanks!
The solution was to log the module name console.log(NativeModules.Something), not the whole NativeModules object. It wasn't anything wrong with my setup.
If you made changes to the native iOS code, then you need to rebuild the project by
rerunning npx react-native run-ios and restart the server npx react-native start.
I also relaunched the app in the simulator.

React Native Redefinition of 'RCTMethodInfo' in RCTBridgeModule.h

React Native 0.49 in iOS I clone my project install npm and link from git and run but it has error in RCTBridgeModule.h in code
typedef struct RCTMethodInfo {
const char *const jsName;
const char *const objcName;
const BOOL isSync;
} RCTMethodInfo;
it have 2 Error
Redefinition of 'RCTMethodInfo' and Typedef redefinition with different types ('struct (anonymous struct at ../../react-native/React/Base/RCTBridgeModule.h:57:16)' vs 'struct RCTMethodInfo')
I fine solution and included
#if __has_include(<React/RCTBridgeModule.h>)
#import <React/RCTBridgeModule.h>
else
#import "RCTBridgeModule.h"
#endif
but it error same
I happend to encountered this issue just now.It was caused by a third party
penguin called "react-native-weibo".I just changed #import "RCTBridgeModule" to #import <React/RCTBridgeModule.h> inside RCTWeiboAPI
,then everything is ok now.
so if your issue is caused by third party penguin also,just try to change #import "xxxx.h" to #import <React/xxxx.h> inside third party API.
Hope it works.
I encountered this issue and solved it by deleting Derived Data. The issue was appear cause of up-gradation of project via xcode 10. Previous project's derived data from xcode 9 also present which was unable to delete by cleaning the project for some reason.
You can manually delete the project build files in Derived Data or use command below.
rm -rf ~/Library/Developer/Xcode/DerivedData
Hope it helps!

RCTBridge is Always Nil

I have been using React Native for a mobile app project for over a year now. I have a native component to bridge the BLE stack to the React Native portion of the app. Recently I upgraded to version 9.1 of XCode and I cannot get the React-Native Bridge to work within the iOS version. The RCTBridge is always nil so I can never use the eventDispatcher(). Here is my setup:
I have a native Swift component which I integrate into the app via a bridgin header. The origanization looks like this:
BLEScanner.swift (This is the native component)
BluetoothModuleBridge.m
Module-Practive-Bridging-Header.h (The bridging header)
Relevant code snippets from each file:
BLEScanner.swift
import Foundation
#objc(BLEScanner)
class BLEScanner: NSObject {
//....
var bridge: RCTBridge! // THIS IS ALWAYS NIL
//....
#objc func requestBluetoothState() -> Void {
print("REQUEST BLE STATE")
let ret = [
"enabled" : true
]
//THIS LINE WILL FAIL BECAUSE bridge IS NIL
self.bridge.eventDispatcher().sendDeviceEvent(withName: "BluetoothStateEvent", body: ret)
}
}
BluetoothModuleBridge.m
#import <React/RCTBridgeModule.h>
#interface RCT_EXTERN_MODULE(BLEScanner, NSObject)
RCT_EXTERN_METHOD(requestBluetoothState)
#end
Module-Practive-Bridging-Header.h
// BluetoothModule-Bridging-Header.h
#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTRootView.h>
#import <React/RCTUtils.h>
#import <React/RCTConvert.h>
#import "AppDelegate.h"
#import "BugsnagReactNative/BugsnagReactNative.h"
#import "nokeLockSDK.h"
#import "nokeServerSDK.h"
#import "TI_aes_128.h"
What I have Tried
Updated React Native from 0.36 to 0.50.3
Tried running on multiple devices
Tried on older version of XCode
Tried compiling on different machine
Compared to a similar app that works and uses this same design.
I am very confused as to why the RCTBridge is returning as nil. It seems odd to me that an XCode update would cause this, however, it is the only change made.
Can anyone point me in the right direction in debugging this issue?
I am using XCode 9.1 and React Native 0.50.3
You do not have to subclass RCTEventEmitter. Just add the #objc attribute. So the variable should be #objc var bridge: RCTBridge!
Do you have your own initial method? If so try remove it. After my test, it has no problem.
And it is recommended to Subclass RCTEventEmitter instead.
If you upgraded to 9.1 and also React Native to 50.x from 30.x at the same time, you could have wrong imports, as that is something that changed around version 40.
It should be
#import <React/RCTBridgeModule.h>
If you don't want to subclass RCTEventEmitter, implement protocol RCTBridgeModule in your BLEScanner.
That will solve the problem.

Resources