jsからnativeを呼び出す
参考
http://facebook.github.io/react-native/docs/nativemodulesios.html#content
Obje-C
#import "RCTBridgeModule.h"
@interface SampleManager : NSObject <RCTBridgeModule>
@end
@implementation SampleManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(callFunc:(NSString *)name param:(NSString *)param dict:(NSDictionary*)dict findEvents:(RCTResponseSenderBlock)callback)
{
NSLog(@"name: %@", name);
NSLog(@"str: %@", param);
NSLog(@"dict: %@", dict);
callback(@[ [NSNull null], @{ @"hoge": @"val" } ]);
}
@end
JS
var SampleManager = require('NativeModules').SampleManager;
SampleManager.callFunc(
'action',
'string_param1',
{ foo: 'bar'},
(error, ret) => {
if (error) {
console.error(error);
} else {
console.log(ret);
}
}
);
nativeからjaコードを呼び出す
RCTRootViewやBridgeModuleのインスタンスにbridgeがあるので、それを使う
ここは公式ドキュメントもちょっと間違ってました
Obje-C
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
[self.rootView.bridge.eventDispatcher sendDeviceEventWithName:@"callFuncName"
body:@{@"name": @"foo"}];
JS
var subscription;
ar SimpleApp = React.createClass({
callFromNative: function(params) {
console.log(params);
this.setState({ name: params.name });
},
componentDidMount: function() {
// 登録
subscription = DeviceEventEmitter.addListener('callFuncName', this.callFromNative);
},
componentWillUnmount: function() {
// 解除
subscription.remove();
},
...
});
Nativeで定義したViewを使う
Swift未対応
Obje-C
- RCTViewManagerを継承する
- RCT_EXPORT_MODULE()
- viewメソッドでViewを返す
#import "RCTViewManager.h"
@interface RCTSampleViewManager : RCTViewManager
@end
@implementation RCTSampleViewManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
UIView* view = [[UIView alloc] init];
view.frame = CGRectMake(0, 0, 100, 100);
view.backgroundColor = [UIColor greenColor];
UILabel* l = [[UILabel alloc] init];
l.text = @"hogehoge";
l.textColor = [UIColor redColor];
[l sizeToFit];
[view addSubview:l];
return view;
}
@end
JS
SampleView.js
'use strict';
var { requireNativeComponent } = require('react-native');
module.exports = requireNativeComponent('RCTSampleView', null);
index.ios.js
var SampleView = require('./SampleView');
...
render() {
return (
<View style={styles.container}>
<Text>Hello ReactNative!!!</Text>
<SampleView />
</View>
);
}
データの永続化
http://facebook.github.io/react-native/docs/asyncstorage.html#content
Cookie
ネイティブとで使っているCookieを引き継ぐことは可能?
無理やりくっつければ可能
#import "ReactNativeSupport.h"
@implementation ReactNativeSupport
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(requestCookies: (RCTResponseSenderBlock)callback)
{
NSDictionary* cookies = @{ @"session_id" : @"hogehogeho" };
callback(@[ [NSNull null], cookies ]);
}
@end
JS
var cookie;
fetchData() {
var cookie = "";
for (var name in cookies) {
cookie += name + "=" + cookies[name] + ";";
}
fetch(API_URL,
{ method: 'POST',
body: JSON.stringify({"foo":"hoge"}),
headers: {
'cookie': cookie,
}
})
.then((response) => {
console.log(response.headers.map['set-cookie']); // Cookieが取得できる
return response.json();
})
.then((responseData) => {
console.log(responseData);
})
.catch((error) => {
console.warn(error);
});
}
componentDidMount() {
var Support = require('NativeModules').ReactNativeSupport;
Support.requestCookies(
(error, ret) => {
if (error) {
console.error(error);
} else {
cookies = ret;
this.fetchData();
}
}
);
headersで指定しない場合は、responseにset-cookieが入ってきても設定されない。
一度headersで指定すれば、次のアクセスからは指定されている
resourceの画像を使う方法
ベクター画像だとうまく動かなかった
pod 'React/RCTImage'
<Image source={require('image!image_name')} />
ハマりどころ
package.jsonは必要!
cocoapodsで作ったプロジェクトや、Integration with Existing Appで作ったプロジェクトでは
packega.jsonを作らないと、別ファイルの読み込みができない。
nodeやってる人には常識かな?
0.4.0以下だとNativeのCustomビューが使えない
コードを細部まで追ってないですが、0.4.1以降を使わないとNativeで定義したViewを使うことができない
ベクター画像は使えない
ドキュメントに書いてないけど読み込めない