React Native 制作iOS静态库供其他原生项目使用
- 工程环境
- 一、用老版本新建项目
- 二、制作静态库
-
-
- 制作静态库分两步:
-
- 1. 生成main.jsbundle。
- 2. 利用项目原本的依赖库,打包一个完整的.a静态库
-
- 三、对外提供
- 四、一些报错处理
-
-
- 1. 真机显示红屏 Unknow argument type '__attribute__' in method -[RCTAppState getCurrentAPpState:error:]. Extend RCTConvert to support this tyoe.
- 2. iphone真机开发者菜单里没有"Enable live Reload和"Enable Hot Reloading"选项,且修改js脚本之后,Reload不生效,不会动态刷新。
-
工程环境
- MacOS : 10.15.6 (19G73)
- Xcode : 12.4
- 测试机:iPhone 6s
- iOS:12.1.4(16D57)
- react-native: 0.44.3
- react native版本用0.44.3,命令行新建项目:
react-native init ProjectName --version 0.44.3
(假设是按照最新官网教程搭建的环境,大概率会)如果提示:react-native commond not found,要先安装下react-native-cli:
yarn global add react-native-cli
二、制作静态库 工程目录结构如下图,老版本项目的ios目录只有一个.xcodeproj项目文件,所以用Xcode12以下也是可以正常打开的。
文章图片
制作静态库分两步:
1. 生成main.jsbundle。
文章图片
可以看到,当前工程中的main.jsbundle脚本资源文件还是空的。
- 启动本地服务器。终端进入项目根目录,输入:
npm start
- 使用curl命令生成 main.jsbundle。开启一个新的终端,进入项目根目录,输入:
curl http://localhost:8081/index.ios.bundle -o main.jsbundle
2. 利用项目原本的依赖库,打包一个完整的.a静态库
- 连真机,直接构建运行项目。构建完成后,可以看到Libraries里的依赖库.a都已生成。
- 随便右键一个.a文件 -> show in finder,可以看到路径
(/Users/xxx/Library/Developer/Xcode/DerivedData/AwsomeTest-gvtvapacxaxwqqasvnndrelfypdp/Build/Products/Debug-iphoneos)下有生成的.a库文件和include文件夹下的头文件,这些都是我们需要的。
文章图片
- 在项目的ios目录下新建一个Libmylib目录,在该文件夹中新建一个静态库工程。
- 将该工程加入到父工程的Libraries中,可以看到父工程的目录结构中已添加了Libmylib子工程。
文章图片
- 在该目录下新建一个Libraries目录,将之前生成的.a库文件和include文件夹拷贝到此目录。
文章图片
- 将子工程的Libraries目录引入到子项目结构中,如下图。
- 删除 除Libmylib.xcodeproj和React.xcodeproj之外的所有依赖库工程。
文章图片
- 先build构建Libmylib.xcodeproj,得到Libmylib.a静态库(deployment target版本需对应)。
- 删除父工程中Build Phases的LibReact.a库的依赖,只保留Libmylib.a。
文章图片
- Libmylib.h中修改:
#import @class No1RootViewController;
@class UIViewController;
#define EXCEPTIONNOTIFICATION @"exceptionCallback_notification"@interface Libmylib : NSObject+ (Libmylib *)sharedManager;
@property (nonatomic, readonly) No1RootViewController* viewController;
-(void)startAPPLaunchConfigWithWindow:(UIViewController *)window didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
// didFinishLaunchingWithOptions 中调用-(void)applicationDidBecomeActive;
// applicationDidBecomeActive 中调用-(void)applicationDidEnterBackground;
// applicationDidEnterBackground 中调用-(void)applicationWillEnterForeground;
// applicationWillEnterForeground 中调用-(void)applicationWillTerminate;
// applicationWillTerminate 中调用-(void)enterCocosRootViewController;
@end
- Libmylib.mm中修改
#import "Libmylib.h"
#import
#import @interface Libmylib()@property (strong, nonatomic) UIView *window;
@end@implementation Libmylib+ (Libmylib *)sharedManager {
static Libmylib *_sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}-(void)startAPPLaunchConfigWithWindow:(UIViewController *)window didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//self.window = window;
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"Libmylib"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
UIViewController *vc = [UIViewController new];
vc.view = rootView;
[window presentViewController:vc animated:YES completion:nil];
}-(void)startAPPLaunchInfoConfigWithWindow:(UIView *)window
{
self.window = window;
}-(void)enterCocosRootViewController
{
}-(void)applicationWillResignActive
{
NSLog(@"Libmylib applicationWillResignActive");
}-(void)applicationDidBecomeActive
{
NSLog(@"Libmylib applicationDidBecomeActive");
}-(void)applicationDidEnterBackground
{
//__cur_no1_app->applicationDidEnterBackground();
}-(void)applicationWillEnterForeground
{//__cur_no1_app->applicationWillEnterForeground();
}-(void)applicationWillTerminate
{
//
//delete __cur_no1_app;
//__cur_no1_app = nil;
}
@end
- 重新构建运行父工程,成功,此时父工程引用的是新打包的静态库,说明新的静态库可用。
- Libmylib.a //静态库文件
- Libmylib.h //头文件
- main.jsbundle //脚本资源文件
代码中调用示例:
第三方ViewController中引入头文件:
#import "Libmylib.h"- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//do something init
[[Libmylib sharedManager] startAPPLaunchConfigWithWindow:viewControllerdidFinishLaunchingWithOptions:launchOptions];
}
四、一些报错处理 1. 真机显示红屏 Unknow argument type ‘attribute’ in method -[RCTAppState getCurrentAPpState:error:]. Extend RCTConvert to support this tyoe.
解决办法: 全局搜索RCTParseUnused这个词,然后修改这个函数的代码:
static BOOL RCTParseUnused(const char **input){
return RCTReadString(input, "__unused") ||
RCTReadString(input, "__attribute__((__unused__))") ||
RCTReadString(input, "__attribute__((unused))");
}
2. iphone真机开发者菜单里没有"Enable live Reload和"Enable Hot Reloading"选项,且修改js脚本之后,Reload不生效,不会动态刷新。
解决办法:
- 检查下终端服务器packer是否开启(一般Xcode构建运行之后,服务会自动开启),否则终端在项目根目录输入:
npm start
- 检查下笔记本和手机是不是在同一网段内,是不是连的同一个wifi。
- AppDelegate.mm中修改,其中192.168.3.29改成自己笔记本当前的IP地址:
jsCodeLocation = [NSURL URLWithString: @"http://192.168.3.29:8081/index.ios.bundle?platform=ios&dev=true"];
推荐阅读
- 微信小程序|微信开发者工具模拟器、IOS真机调试、Android真机调试中Editor效果不一致问题
- iOS开发记录|iOS 关于Safari浏览器和Chrome浏览器Video标签的区别
- 微信小程序|微信小程序项目实例——幸运大转盘
- Javascript|JavaScript权威指南7(四) 第十一章 JavaScript 标准库
- 数码科技|用了三年的苹果手机,才发现 iPhone 翻译真好用,堪比译员的水准
- 技能分享|iPhone彻底删除的照片能恢复吗,2个找回永久删除照片的方法
- flutter学习|flutter+Dart类的创建(六)
- iOS移动开发|苹果春季发布会看点汇总
- iOS移动开发|苹果发布会汇总(最便宜 5G iPhone 不是主角,M1 Ultra 傲视一切)