React Native(iOS)新手小白零基础自学(十二)Na

2016-06-12  本文已影响613人  神魔狼

前面看了一大段,看不懂,好乱啊!!!直接实战开始吧。
1.创建一个Native模块:获得当前屏幕尺寸Dimensions,并且提供注册事件监控屏幕方向变化。

首先,我们在项目工程中创建Native模块类RCTDeviceExtension,继承RCTBridgeModule协议:

![EB431DC7-F27F-46B6-A948-B0B7C69A37C6.png](https://img.haomeiwen.com/i1712038/132bc558934715d6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后我们在index.ios.js里:

var React = require('react-native');

 var {
   AppRegistry,
   StyleSheet,
   View,
   Text
 } = React;

 //立即执行
 var immediateID = setImmediate(function(){
   console.log(require('NativeModules'));
 });

var app = React.createClass({
  render:function(){
    return(
      <View>

      </View>
    );
  },



});

var styles = StyleSheet.create({

});

AppRegistry.registerComponent('RNOldVersionES5', () => app);

结果:说明RCTDeviceExtension模块已经被加载到模块配置中了,同时在JavaScript模块中生成了DeviceExtension对象

2D0FB06D-5DEB-41B5-9F35-204129D207CC.png

然后,开始实现模块方法。
在RCTDeviceExtension.m文件中添加如下代码

#import "RCTDeviceExtension.h"
#import "RCTUtils.h"
#import "RCTEventDispatcher.h"
#import "RCTConvert.h"

static NSDictionary *CurrentDimensions(){
  //提供当前屏幕的尺寸
  CGFloat width = MIN(RCTScreenSize().width, RCTScreenSize().height);
  CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
  CGFloat scale = RCTScreenScale();
  if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
    width = MAX(RCTScreenSize().width, RCTScreenSize().height);
    height = MIN(RCTScreenSize().width, RCTScreenSize().height);
  }
  return @{@"width":@(width),
           @"height":@(height),
           @"scale":@(scale)};
}

@implementation RCTDeviceExtension

@synthesize bridge = _bridge;

//向系统注册模块。 ()内不填,会默认使用类名来作为模块名
RCT_EXPORT_MODULE();

- (instancetype)init
{
  self = [super init];
  if (self) {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
  }
  return self;
}

/*
  常量导出
  如下,则可以在JavaScript中直接访问字典的key值来访问字典对象
*/
- (NSDictionary *)constantsToExport
{
  return @{@"EVENT_ORIENTATION":@"orientationDidChange"};
}

#pragma mark - Notification Selector
- (void)orientationDidChange:(id)noti
{
  //通过RCTEventDispatcher将事件orientationDidChange通知到JavaScript,这里要引入RCTEventDispatcher头文件。
  //- (void)sendDeviceEventWithName:(NSString *)name body:(id)body;
  //发送设备相关的事件,例如地理定位和屏幕旋转
  [_bridge.eventDispatcher sendDeviceEventWithName:@"orientationDidChange"
                                              body:@{@"Orientation":UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? @"Landscape":@"Portrait",
                                                     @"Dimensions":CurrentDimensions()}];
}

#pragma mark - Public APIs
/*
 RCT_EXPORT_METHOD(js_name, method) 暴露模块方法
 一般情况下,我们都使用RCTResponseSenderBlock来作为回调函数,此时只需要将一个NSArray对象传入块函数执行即可
*/
RCT_EXPORT_METHOD(getCurrentDimensions:(RCTResponseSenderBlock)callback) {
  
  callback(@[[NSNull null], CurrentDimensions()]);
  
}

- (void)dealloc
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}


@end

然后在ios.js中使用:

var DeviceExtension = require('NativeModules').DeviceExtension;//屏幕尺寸
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');//屏幕旋转

DeviceExtension.getCurrentDimensions((error, dimensions) => {
  console.log(dimensions);
});

var subscription = RCTDeviceEventEmitter.addListener('orientationDidChange', (dimensions) => {
  console.log(dimensions);
});

最后若要把模块做成第三方组件的话,还要做些操作。这里我遇到了点问题暂未解决,暂不上传了。。。等我解决后再上传-_-!!

上一篇下一篇

猜你喜欢

热点阅读