当前位置: 首页 > news >正文

全国网站建设公司排名wordpress功能强大的主题

全国网站建设公司排名,wordpress功能强大的主题,cookies因预料之外的输出被阻止 wordpress,推进政务服务网站一体化建设有时候App需要访问平台API#xff0c;但React Native可能还没有相应的模块封装#xff1b;或者你需要复用Objective-C、Swift或C代码#xff0c;而不是用JavaScript重新实现一遍#xff1b;又或者你需要实现某些高性能、多线程的代码#xff0c;譬如图片处理、数据库、或者… 有时候App需要访问平台API但React Native可能还没有相应的模块封装或者你需要复用Objective-C、Swift或C代码而不是用JavaScript重新实现一遍又或者你需要实现某些高性能、多线程的代码譬如图片处理、数据库、或者各种高级扩展等等。 我们把React Native设计为可以在其基础上编写真正的原生代码并且可以访问平台所有的能力。这是一个相对高级的特性我们并不认为它应当在日常开发的过程中经常出现但具备这样的能力是很重要的。如果React Native还不支持某个你需要的原生特性你应当可以自己实现该特性的封装。 本文是关于如何封装原生模块的高级向导我们假设您已经具备Objective-C或者Swift以及iOS核心库Foundation、UIKit的相关知识。 iOS 日历模块演示 本向导将会用iOS日历API作为示例。我们的目标就是在Javascript中可以访问到iOS的日历功能。 在React Native中一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类其中RCT是ReaCT的缩写。 // CalendarManager.h #import RCTBridgeModule.hinterface CalendarManager : NSObject RCTBridgeModule end为了实现RCTBridgeModule协议你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定默认就会使用这个Objective-C类的名字。 // CalendarManager.m implementation CalendarManagerRCT_EXPORT_MODULE();end你必须明确的声明要给Javascript导出的方法否则React Native不会导出任何方法。声明通过RCT_EXPORT_METHOD()宏来实现 RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location) {RCTLogInfo(Pretending to create an event % at %, name, location); }现在从Javascript里可以这样调用这个方法 var CalendarManager require(react-native).NativeModules.CalendarManager; CalendarManager.addEvent(Birthday Party, 4 Privet Drive, Surrey);注意: Javascript方法名 导出到Javascript的方法名是Objective-C的方法名的第一个部分。React Native还定义了一个RCT_REMAP_METHOD()宏它可以指定Javascript方法名。当许多方法的第一部分相同的时候用它来避免在Javascript端的名字冲突。 桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的所以要返回结果给Javascript你必须通过回调或者触发事件来进行。参见本文档后面的部分 参数类型 RCT_EXPORT_METHOD 支持所有标准JSON类型包括 string (NSString)number (NSInteger, float, double, CGFloat, NSNumber)boolean (BOOL, NSNumber)array (NSArray) 包含本列表中任意类型map (NSDictionary) 包含string类型的键和本列表中任意类型的值function (RCTResponseSenderBlock) 除此以外任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数用来接收一个JSON值并转换到原生Objective-C类型或类。 在我们的CalendarManager例子里我们需要把事件的时间交给原生方法。我们不能在桥接通道里传递Date对象所以需要把日期转化成字符串或数字来传递。我们可以这么实现原生函数 RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSNumber *)secondsSinceUnixEpoch) {NSDate *date [RCTConvert NSDate:secondsSinceUnixEpoch]; }或者这样 RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSString *)ISO8601DateString) {NSDate *date [RCTConvert NSDate:ISO8601DateString]; }不过我们可以依靠自动类型转换的特性跳过手动的类型转换而直接这么写 RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSDate *)date) {// Date is ready to use! }在Javascript既可以这样 CalendarManager.addEvent(Birthday Party, 4 Privet Drive, Surrey, date.getTime()); // 把日期以unix时间戳形式传递也可以这样 CalendarManager.addEvent(Birthday Party, 4 Privet Drive, Surrey, date.toISOString()); // 把日期以ISO-8601的字符串形式传递两个值都会被转换为正确的NSDate类型。但如果提供一个不合法的值譬如一个Array则会产生一个“红屏”报错信息。 随着CalendarManager.addEvent方法变得越来越复杂参数的个数越来越多其中有一些可能是可选的参数。在这种情况下我们应该考虑修改我们的API用一个dictionary来存放所有的事件参数像这样 #import RCTConvert.hRCT_EXPORT_METHOD(addEvent:(NSString *)name details:(NSDictionary *)details) {NSString *location [RCTConvert NSString:details[location]];NSDate *time [RCTConvert NSDate:details[time]];... }然后在JS里这样调用 CalendarManager.addEvent(Birthday Party, {location: 4 Privet Drive, Surrey,time: date.toTime(),description: ... })注意: 关于数组和映射 Objective-C并没有提供确保这些结构体内部值的类型的方式。你的原生模块可能希望收到一个字符串数组但如果JavaScript在调用的时候提供了一个混合number和string的数组你会收到一个NSArray里面既有NSNumber也有NSString。对于数组来说RCTConvert提供了一些类型化的集合譬如NSStringArray或者UIColorArray你可以用在你的函数声明中。对于映射而言开发者有责任自己调用RCTConvert的辅助方法来检测和转换值的类型。 回调函数 警告 本章节内容目前还处在实验阶段因为我们还并没有太多的实践经验来处理回调函数。 原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给JavaScript。 RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback) {NSArray *events ...callback([[NSNull null], events]); }RCTResponseSenderBlock只接受一个参数——传递给JavaScript回调函数的参数数组。在上面这个例子里我们用Node.js的常用习惯第一个参数是一个错误对象没有发生错误的时候为null而剩下的部分是函数的返回值。 CalendarManager.findEvents((error, events) {if (error) {console.error(error);} else {this.setState({events: events});} })原生模块通常只应调用回调函数一次。但是它可以保存callback并在将来调用。这在封装那些通过“委托函数”来获得返回值的iOS API时最为常见。RCTAlertManager中就属于这种情况。 如果你想传递一个更接近Error类型的对象给Javascript可以用RCTUtils.h提供的RCTMakeError函数。现在它仅仅是发送了一个和Error结构一样的dictionary给Javascript但我们考虑在将来版本里让它产生一个真正的Error对象。 Promises 译注这一部分涉及到较新的js语法和特性不熟悉的读者建议先阅读ES6的相关书籍和文档。 原生模块还可以使用promise来简化代码搭配ES2016(ES7)标准的async/await语法则效果更佳。如果桥接原生方法的最后两个参数是RCTPromiseResolveBlock和RCTPromiseRejectBlock则对应的JS方法就会返回一个Promise对象。 我们把上面的代码用promise来代替回调进行重构 RCT_REMAP_METHOD(findEvents,resolver:(RCTPromiseResolveBlock)resolverejecter:(RCTPromiseRejectBlock)reject)) {NSArray *events ...if (events) {resolve(events);} else {reject(error);} }现在JavaScript端的方法会返回一个Promise。这样你就可以在一个声明了async的异步函数内使用await关键字来调用并等待其结果返回。虽然这样写着看起来像同步操作但实际仍然是异步的并不会阻塞执行来等待。 async function updateEvents() {try {var events await CalendarManager.findEvents();this.setState({ events });} catch (e) {console.error(e);} }updateEvents();多线程 原生模块不应对自己被调用时所处的线程做任何假设。React Native在一个独立的串行GCD队列中调用原生模块的方法但这属于实现的细节并且可能会在将来的版本中改变。通过实现方法- (dispatch_queue_t)methodQueue原生模块可以指定自己想在哪个队列中被执行。具体来说如果模块需要调用一些必须在主线程才能使用的API那应当这样指定 - (dispatch_queue_t)methodQueue {return dispatch_get_main_queue(); }类似的如果一个操作需要花费很长时间原生模块不应该阻塞住而是应当声明一个用于执行操作的独立队列。举个例子RCTAsyncLocalStorage模块创建了自己的一个queue这样它在做一些较慢的磁盘操作的时候就不会阻塞住React本身的消息队列 - (dispatch_queue_t)methodQueue {return dispatch_queue_create(com.facebook.React.AsyncLocalStorageQueue, DISPATCH_QUEUE_SERIAL); }指定的methodQueue会被你模块里的所有方法共享。如果你的方法中“只有一个”是耗时较长的或者是由于某种原因必须在不同的队列中运行的你可以在函数体内用dispatch_async方法来在另一个队列执行而不影响其他方法 RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback) {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 在这里执行长时间的操作...// 你可以在任何线程/队列中执行回调函数callback([...]);}); }注意: 在模块之间共享分发队列 methodQueue方法会在模块被初始化的时候被执行一次然后会被React Native的桥接机制保存下来所以你不需要自己保存队列的引用除非你希望在模块的其它地方使用它。但是如果你希望在若干个模块中共享同一个队列则需要自己保存并返回相同的队列实例仅仅是返回相同名字的队列是不行的。 导出常量 原生模块可以导出一些常量这些常量在JavaScript端随时都可以访问。用这种方法来传递一些静态数据可以避免通过bridge进行一次来回交互。 - (NSDictionary *)constantsToExport {return { firstDayOfTheWeek: Monday }; }Javascript端可以随时同步地访问这个数据 console.log(CalendarManager.firstDayOfTheWeek);但是注意这个常量仅仅在初始化的时候导出了一次所以即使你在运行期间改变constantToExport返回的值也不会影响到JavaScript环境下所得到的结果。 枚举常量 用NS_ENUM定义的枚举类型必须要先扩展对应的RCTConvert方法才可以作为函数参数传递。 假设我们要导出如下的NS_ENUM定义 typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {UIStatusBarAnimationNone,UIStatusBarAnimationFade,UIStatusBarAnimationSlide, };你需要这样来扩展RCTConvert类 implementation RCTConvert (StatusBarAnimation)RCT_ENUM_CONVERTER(UIStatusBarAnimation, ({ statusBarAnimationNone : (UIStatusBarAnimationNone),statusBarAnimationFade : (UIStatusBarAnimationFade),statusBarAnimationSlide : (UIStatusBarAnimationSlide)},UIStatusBarAnimationNone, integerValue) end接着你可以这样定义方法并且导出enum值作为常量 - (NSDictionary *)constantsToExport {return { statusBarAnimationNone : (UIStatusBarAnimationNone),statusBarAnimationFade : (UIStatusBarAnimationFade),statusBarAnimationSlide : (UIStatusBarAnimationSlide) } };RCT_EXPORT_METHOD(updateStatusBarAnimation:(UIStatusBarAnimation)animationcompletion:(RCTResponseSenderBlock)callback)你的枚举现在会用上面提供的选择器进行转换上面的例子中是integerValue然后再传递给你导出的函数。 给Javascript发送事件 即使没有被JavaScript调用本地模块也可以给JavaScript发送事件通知。最直接的方式是使用eventDispatcher: #import RCTBridge.h #import RCTEventDispatcher.himplementation CalendarManagersynthesize bridge _bridge;- (void)calendarEventReminderReceived:(NSNotification *)notification {NSString *eventName notification.userInfo[name];[self.bridge.eventDispatcher sendAppEventWithName:EventReminderbody:{name: eventName}]; }end在JavaScript中可以这样订阅事件 var { NativeAppEventEmitter } require(react-native);var subscription NativeAppEventEmitter.addListener(EventReminder,(reminder) console.log(reminder.name) ); ... // 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。 subscription.remove();更多的给JavaScript发送事件的例子参见RCTLocationObserver. 从Swift导出 Swift不支持宏所以从Swift向React Native导出类和函数需要多做一些设置但是大致与Objective-C是相同的。 假设我们已经有了一个一样的CalendarManager不过是用Swift实现的类: // CalendarManager.swiftobjc(CalendarManager) class CalendarManager: NSObject {objc func addEvent(name: String, location: String, date: NSNumber) - Void {// Date is ready to use!}}注意: 你必须使用objc标记来确保类和函数对Objective-C公开。 接着创建一个私有的实现文件并将必要的信息注册到React Native中。 // CalendarManagerBridge.m #import RCTBridgeModule.hinterface RCT_EXTERN_MODULE(CalendarManager, NSObject)RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)date)end请注意一旦你在IOS中混用2种语言, 你还需要一个额外的桥接头文件称作“bridging header”用来导出Objective-C文件给Swift。如果你是通过Xcode菜单中的FileNew File来创建的Swift文件Xcode会自动为你创建这个头文件。在这个头文件中你需要引入RCTBridgeModule.h。 // CalendarManager-Bridging-Header.h #import RCTBridgeModule.h同样的你也可以使用RCT_EXTERN_REMAP_MODULE和RCT_EXTERN_REMAP_METHOD来改变导出模块和方法的JavaScript调用名称。 了解更多信息请参阅RCTBridgeModule. 本文转自React Native中文网http://reactnative.cn/docs/0.20/native-modules-ios.html#content
http://www.pierceye.com/news/905766/

相关文章:

  • 做网站用c 还是php番禺制作网站平台
  • 营销网站运营的基本环节郑州大学现代远程教育 《网页设计与网站建设》个人主页
  • 网站建设合同是谁开的wordpress装主题需要ftp
  • 新乡门户网站建设方案开启wordpress upwn
  • 烟台企业自助建站系统浙江网站seo
  • 北京婚纱摄影网站珠海网站建设怎样
  • 用什么软件来做网站域名网安备案
  • 能打开各种网站的浏览器推荐制作小网站
  • 山东公司网站开发好看的个人博客主页
  • 长沙优化网站获客软件最新网页游戏排行榜2021
  • 学校网站 建设网络系统管理与维护电大考试题
  • 中文域名转码网站琼筑网站是哪家做的
  • iis 网站访问权限毕设做网站的过程
  • 俱乐部网站模板有什么外贸网站
  • 补习吧 一家专门做家教的网站wordpress繁体字插件
  • 北京西站附近景点网络运营工作内容
  • 网站开发文档模板flask网站开发源码
  • 东莞清洁服务网站建设wordpress收费主题
  • 微网站如何做门户网站建设成都
  • 厦门网络推广建网站前端做图表的网站
  • 河南郑州网站设计公司手机自助建网站
  • 做网站的公司主要做shm有域名了网站怎么做
  • 竭诚网络网站建设价格贺兰网站建设
  • 部门网站管理建设工作汇报wordpress一键生成app
  • 帝国视频网站模板做网站的环境配置
  • 龙采科技做网站多少钱域名如何申请
  • 中国银行全球门户网站wordpress 分类下排序
  • 网站费用怎么做帐张北网站建设
  • 郑州专业网站制作泉州网络推广专员
  • 此网站可能有优化大师班级