1: 项目的初始化
npx react-native init MyApp --template react-native-template-typescript
使用react-native typescript的默认构建命令初始化项目
2: 依赖安装
// npm依赖的安装
npm install
// ios的cocoapods依赖的安装
cd ios
pod install
// cocoapods的依赖安装特别久......
2.1 cocoapods安装的加速
CocoaPods 是一个 Cocoa 和 Cocoa Touch 框架的依赖管理器,具体原理和 Homebrew 有点类似,都是从 GitHub 下载索引,然后根据索引下载依赖的源代码。
对于旧版的 CocoaPods 可以使用如下方法使用 tuna 的镜像:
$ pod repo remove master
$ pod repo add master https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git
$ pod repo update
复制代码
新版的 CocoaPods 不允许用pod repo add
直接添加master库了,但是依然可以:
$ cd ~/.cocoapods/repos
$ pod repo remove master
$ git clone https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git master
复制代码
最后进入自己的工程,在自己工程的podFile
第一行加上:
source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
一些库的安装
有React-Navigation, React-Native-Elements, React-Native-Vector-Icons等,相关安装流程可参考其官方文档。
ios的启动调整为:自定义的原生视图
首先展示下RN默认创建的AppDelegate.m文件的didFinishLaunchingWithOptions方法内容:
- (**BOOL**)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"DingApp";
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
调整后:rootViewController将作为自定义的根视图。
在AppDelegate.m的文件顶部导入,让OC识别项目中的swift代码
#import <项目名-Swift.h>
- (**BOOL**)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
ios获取屏幕大小
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
react-native集成swift原生组件
这里仅将swift组件抛出去,还没有添加属性,方法,事件。
// 创建TeMetroViewManager.m文件,内容如下:
@interface RCT_EXTERN_MODULE(TeMetroViewManager, RCTViewManager)
// 导出TeMetroView内的方法: buildMapSize
RCT_EXTERN_METHOD (
buildMapSize:(nonnull NSNumber *)node
width:(nonnull CGFloat *)width
height:(nonnull CGFloat *)height
)
@end
// 创建TeMetroViewManager.swift文件,内容如下:
// TeMetroView是ios内的一个swift组件
@objc(TeMetroViewManager)
class TeMetroViewManager: RCTViewManager {
// 这里返回swift组件
override func view() -> UIView {
return TeMetroView()
}
override static func requiresMainQueueSetup() -> Bool {
return true
}
// 根据node获取所在的视图
private func getTargetView(node: NSNumber) -> TeMetroView? {
if let view = self.bridge.uiManager.view(forReactTag: node) {
return view as? TeMetroView
}
return nil
}
// buildMapSize是提供给RN调用的
@objc public func buildMapSize(_ node: NSNumber, width: CGFloat, height: CGFloat) {
DispatchQueue.main.async {
guard let targetView = self.getTargetView(node: node) else {
return
}
targetView.buildMapSize(width: width, height: height)
}
}
}
// 在react-native目录下创建te-metro-native-view.ts文件,内容如下:
import {requireNativeComponent} from 'react-native';
import TeMetroNativeViewProps from './TeMetroNativeViewProps';
// requireNativeComponent 自动把'TeMetroView'解析为'TeMetroViewManager'
export default requireNativeComponent<TeMetroNativeViewProps>('TeMetroView');
// 在react-native目录下创建TeMetroView.tsx组件文件,内容如下:
import {StyleSheet} from 'react-native';
import TeMetroNativeView from './TeMetroNativeView';
import TeMetroViewProps from './TeMetroViewProps';
export default function TeMetroView(props: TeMetroViewProps) {
return <TeMetroNativeView style={{...styles.containerView}} />;
}
// 包装的原生UI组件的flex设置为1,可以全部填充父组件。
const styles = StyleSheet.create({
containerView: {
flex: 1,
},
});
// rn调用swifu组件内的方法
const manager: any = UIManager;
manager.dispatchViewManagerCommand(
findNodeHandle(nativeRef.current),
manager.TeMetroView.Commands.buildMapSize,
[width, height],
);
ios像canvas一样绘制内容
// UIGraphicsGetCurrentContext必须在draw函数中使用
guard let context = UIGraphicsGetCurrentContext() else {
return
}
// 对context的使用在canvas的使用思路是一样的。
// 将原生ios的canvas背景设置为透明
UIColor(white: 1, alpha: 0)
// 调用setNeedsDisplay会触发ios系统对canvasView进行重绘,进而执行其draw方法。
self.canvasView.setNeedsDisplay()