macOS Mojave Version 10.14.3
Xcode 10.1
iPhone 5s 10.0.1
node v11.10.0
npm 6.7.0
React Native 0.58
react 16.6.3
ReactNative
项目brew install node
brew install watchman
React Native
命令行工具npm install -g react-native-cli
Xcode
及命令行相关工具## man xcode-select
## xcode-select - Manages the active developer directory for Xcode and BSD
## tools.
## --install
## Opens a user interface dialog to request automatic installation
## of the command line developer tools.
xcode-select --install
详情参考英文-doc 链接2/中文-doc 链接11
react-native init AwesomeProject
若node
版本过低可能出现Command yarn add react-native --exact` failed.
,可参考Upgrade Node.js to the latest version on Mac OS升级node
观察日志的输出生成工程执行的是
/Users/`userName`/.nvm/versions/node/v11.10.0/bin/node /Users/`userName`/.nvm/versions/node/v11.10.0/lib/node_modules/react-native-cli/index.js init AwesomeProject
查看react-native
位置
which react-native
## 输出
/Users/`userName`/.nvm/versions/node/v11.10.0/bin/react-native
React Native
应用同样根据窗口日志的输出,iOS
运行的方法可以用命令行或直接使用Xcode
打开运行
使用命令行方式
## cd到工程目录下
cd /Users/`userName`/WebstormProjects/AwesomeProject
## 执行
react-native run-ios
Found Xcode project AwesomeProject.xcodeproj
... bla bla bla
> Running script 'Install Third Party'
启动模拟器,然后安装下载第三方的组件,下载的脚本是scripts/ios-install-third-party.sh
if [ -d "$HOME/.rncache" ]; then
cachedir="$HOME/.rncache" # react-native 0.57.8 and older
else
cachedir="$HOME/Library/Caches/com.facebook.ReactNativeBuild"
fi
mkdir -p "$cachedir"
...
缓存目录旧版在家目录的.rncache
,如果存在该目录,则下载的库就会安装在此处,若网络原因无法下载,可参考iOS RN 0.45以上版本所需的第三方编译库(boost等),手动下载即可
但是,运行失败了
Installing build/Build/Products/Debug-iphonesimulator/AwesomeProject.app
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
Failed to install the requested application
The bundle identifier of the application could not be determined.
Ensure that the application's Info.plist contains a value for CFBundleIdentifier.
Print: Entry, ":CFBundleIdentifier", Does Not Exist
Command failed: /usr/libexec/PlistBuddy -c Print:CFBundleIdentifier build/Build/Products/Debug-iphonesimulator/AwesomeProject.app/Info.plist
Print: Entry, ":CFBundleIdentifier", Does Not Exist
Error: Command failed: /usr/libexec/PlistBuddy -c Print:CFBundleIdentifier build/Build/Products/Debug-iphonesimulator/AwesomeProject.app/Info.plist
Print: Entry, ":CFBundleIdentifier", Does Not Exist
at checkExecSyncError (child_process.js:637:11)
at Object.execFileSync (child_process.js:655:13)
at Promise.then (/Users/Jason/WebstormProjects/AwesomeProject/node_modules/react-native/local-cli/runIOS/runIOS.js:208:5)
at processTicksAndRejections (internal/process/next_tick.js:81:5)
再往上看,编译时就已经失败了
❌ /Users/Jason/WebstormProjects/AwesomeProject/node_modules/react-native/third-party/folly-2018.10.22.00/folly/detail/RangeCommon.h:22:10: 'glog/logging.h' file not found
#include
^
用Xcode
的方式试试
选择模拟器并编译
除了jsi
中RangeCommon.h
的glog/logging.h
找不到以外,这个与使用命令行运行时是一样,又多了三个错误,剩下的3个错误,参考Supporting Xcode 10 and the new Xcode build system,RN
的一个issue
,调整工程的编译系统,再次编译
现在错误变成一样了,都是文件找不到,来看看为什么找不到,React.xcodeproj
> ThirdParty
> glog
> glog
下,确实缺少文件
jsi
依赖于double-conversion
double-conversion
执行了ios-install-third-party.sh
,并未能成功输出需要的头文件
## ios-install-third-party.sh
function fetch_and_unpack () {
file=$1
url=$2
hash=$3
cmd=$4
...
if [ "$fetched" = "yes" ] || [ ! -f "third-party/$dir/.installed" ]; then
(cd third-party;
## <2>
rm -rf "$dir"
echo Unpacking "$cachedir/$file"...
if ! tar zxf "$cachedir/$file"; then
file_fail "$cachedir/$file" "Unpacking '$cachedir/$file' failed"
fi
cd "$dir"
eval "${cmd:-true}" && touch .installed)
fi
}
## <1>
mkdir -p third-party
SCRIPTDIR=$(dirname "$0")
fetch_and_unpack glog-0.3.5.tar.gz https://github.com/google/glog/archive/v0.3.5.tar.gz 61067502c5f9769d111ea1ee3f74e6ddf0a5f9cc "\"$SCRIPTDIR/ios-configure-glog.sh\""
...
cd
到third-party
目录,将缓存目录下的包解压缩,并执行对应的指令,比如glog-0.3.5
就执行
$SCRIPTDIR/ios-configure-glog.sh
### ios-configure-glog.sh
./configure --host arm-apple-darwin
# Fix build for tvOS
cat << EOF >> src/config.h
...
# Prepare exported header include
EXPORTED_INCLUDE_DIR="exported/glog"
mkdir -p exported/glog
cp -f src/glog/log_severity.h "$EXPORTED_INCLUDE_DIR/"
cp -f src/glog/logging.h "$EXPORTED_INCLUDE_DIR/"
cp -f src/glog/raw_logging.h "$EXPORTED_INCLUDE_DIR/"
cp -f src/glog/stl_logging.h "$EXPORTED_INCLUDE_DIR/"
cp -f src/glog/vlog_is_on.h "$EXPORTED_INCLUDE_DIR/"
执行该脚本执行configure
并创建exported/glog
目录,然后将configure
过程中生成的文件cp
到该目录,执行ios-configure-glog.sh
后
结果如下:
这是正常的,但是⌘ + B
再次编译后又报了相同的错误,对比Xcode
与终端执行的日志结果发现,Xcode
执行时checking whether the C compiler works...
失败了
关于'glog/logging.h' file not found
,根据’glog/logging.h’ file not found得到的解决方案是
cd node_modules/react-native/third-party/glog-0.3.5
sh ../../scripts/ios-configure-glog.sh
上面已经执行过了,用Xcode
重新编译还会出现问题
参考react-native/pull/23511
手动修改ios-configure-glog.sh
文件
...
export CXX="$(xcrun -find -sdk $PLATFORM_NAME cc) -arch $CURRENT_ARCH -isysroot $(xcrun -sdk $PLATFORM_NAME --show-sdk-path)"
...
试了以后,用Xcode
编译依然报错ㄟ( ▔, ▔ )ㄏ
../../
在上面的代码的<1>处可知,../..
后,当前位置会在.../react-native
目录下,要在该目录下创建third-party
目录,同时又要保证SCRIPTDIR
能正确定位到ios-configure-glog.sh
去执行。
这样做后还是失败,因为<2>处移除后,重新执行,同样因为configure
失败导致无法生成.h
文件。
在终端根据上面提到的方法执行ios-install-third-party.sh
后
# 注释下面这句
# fetch_and_unpack glog-0.3.5.tar.gz https://github.com/google/glog/archive/v0.3.5.tar.gz 61067502c5f9769d111ea1ee3f74e6ddf0a5f9cc "\"$SCRIPTDIR/ios-configure-glog.sh\""
避免去删除glog
这个包,然后再用Xcode进行编译就正常了,运行时模拟器下还是会崩溃,真机能正常运行。
资源地址获取不正确,有网络代理工具的情况时,比如SS
,将其调成自动代理或关闭
Hello world
修改App.js
export default class App extends Component<Props> {
render() {
// return (
//
// Welcome to React Native!
// To get started, edit App.js
// {instructions}
//
// );
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center",backgroundColor: '#F5FCFF', }}>
<Text>Hello world!</Text>
</View>
);
}
}
要使用backgroundColor: '#F5FCFF'
设置背景色
ReactNative
到已有项目新建一个目录去集成RN
工程,将Xcode
工程复制到RN
下的ios
子目录
JavaScript
依赖库在RN
工程根目录下,创建package.json
文件
{
"name": "AnNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
}
}
## 若 yarn 不存在,安装
## brew install yarn
yarn add react-native
## 安装React
# warning " > [email protected]" has unmet peer dependency "[email protected]".
# 而且原来使用``WebStorm``生成的``package.json``中包含的``react``和``react-native``,所以``react``也选16.6.3
# "dependencies": {
# "react": "16.6.3",
# "react-native": "0.58.5"
# },
yarn add react@version_printed_above
把node_modules
添加到.gitignore
文件中
# 将``WebStorm``生成的.gitignore复制到``RN``根目录下即可
cp .gitignore ~/Desktop/AnNativeApp/
CocoaPods
集成在ios
目录下,初始化pod init
配置
pod init
platform :ios, '9.0'
target 'AnNativeApp' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Your 'node_modules' directory is probably in the root of your project,
# but if not, adjust the `:path` accordingly
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge', # Include this for RN >= 0.47
'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43
'RCTText',
'RCTNetwork',
'RCTWebSocket', # Needed for debugging
'RCTAnimation', # Needed for FlatList and animations running on native UI thread
# Add any other subspecs you want to use in your project
]
# Explicitly include Yoga if you are using RN >= 0.42.0
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
# Third party deps podspec link
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
target 'AnNativeAppTests' do
inherit! :search_paths
# Pods for testing
end
target 'AnNativeAppUITests' do
inherit! :search_paths
# Pods for testing
end
end
pod install
可能会碰到如下的错误
...
Installing boost-for-react-native (1.63.0)
[!] Error installing boost-for-react-native
[!] /usr/local/bin/git clone https://github.com/react-native-community/boost-for-react-native.git /var/folders/lk/znn1qp4925j412wt4t_qkplc0000gn/T/d20190222-11171-yp7x2 --template= --single-branch --depth 1 --branch v1.63.0-0
Cloning into '/var/folders/lk/znn1qp4925j412wt4t_qkplc0000gn/T/d20190222-11171-yp7x2'...
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
因为仓库太大了,搜索后大致有两种办法
方式一
## man git-config
## http.postBuffer
## Maximum size in bytes of the buffer used by smart HTTP transports when POSTing data to the remote system. For requests larger than
## this buffer size, HTTP/1.1 and Transfer-Encoding: chunked is used to avoid creating a massive pack file locally. Default is 1 MiB,
## which is sufficient for most requests.
git config --global http.postBuffer 524288000
方式二
git clone http://github.com/large-repository --depth 1
cd large-repository
git fetch --unshallow
使用了方式一正常解决了。因为根据错误信息说明已经是用--depth 1
去下载了,但是可以去了解一下
通过[!] Error installing
作为关键词去CocoaPods搜索
CocoaPods/lib/cocoapods/downloader/cache.rb
# Downloads the Pod from the given `request`
#
# @param [Request] request
# the request to be downloaded.
#
# @return [Response] the response from downloading `request`
#
def download_pod(request)
cached_pod(request) || uncached_pod(request)
rescue Informative
raise
rescue
raise
end
调用
def cached_pod(request)
cached_spec = cached_spec(request)
path = path_for_pod(request)
return unless cached_spec && path.directory?
spec = request.spec || cached_spec
Response.new(path, spec, request.params)
end
因为是用gem
安装的
gem env
获得gem
包的安装位置,定位到cache.rb
,经过一些步骤之后,
cocoapods-downloader/lib/cocoapods-downloader/git.rb
# Clones the repo. If possible the repo will be shallowly cloned.
#
# @note The `:commit` option requires a specific strategy as it is not
# possible to specify the commit to the `clone` command.
#
# @note `--branch` command line option can also take tags and detaches
# the HEAD.
#
# @param [Bool] force_head
# If any specific option should be ignored and the HEAD of the
# repo should be cloned.
#
# @param [Bool] shallow_clone
# Whether a shallow clone of the repo should be attempted, if
# possible given the specified {#options}.
#
def clone(force_head = false, shallow_clone = true)
ui_sub_action('Git download') do
begin
git! clone_arguments(force_head, shallow_clone)
update_submodules
rescue DownloaderError => e
if e.message =~ /^fatal:.*does not support (--depth|shallow capabilities)$/im
clone(force_head, false)
else
raise
end
end
end
end
index.js
&& 添加RN
代码可以参考WebStorm
创建的index.js
和App.js
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
// <1>
class RNHighScores extends React.Component {
render() {
var contents = this.props['scores'].map((score) => (
<Text key={score.name}>
{score.name}:{score.value}
{'\n'}
</Text>
));
return (
<View style={styles.container}>
<Text style={styles.highScoresTitle}>2048 High Scores!</Text>
// <2>
<Text style={styles.scores}>{contents}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
...
},
highScoresTitle: {
fontSize: 20,
...
},
scores: {
textAlign: 'center',
...
},
});
RCTRootView
在Xcode
的ViewController
中
// <3>
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://192.168.31.191:8081/index.bundle?platform=ios"];
// [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: @"AnNativeApp" // <4>
initialProperties:
@{
@"scores" : @[
@{
@"name" : @"Alex",
@"value": @"42"
},
@{
@"name" : @"Joel",
@"value": @"10"
}
]
}
launchOptions: nil];
// <5>
[self.view addSubview:rootView];
<key>NSAppTransportSecuritykey>
<dict>
<key>NSExceptionDomainskey>
<dict>
<key>localhostkey>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoadskey>
<true/>
dict>
dict>
dict>
npm start
然后就可以运行Xcode
项目,观察效果了
<1> 教程中是把所有的都写在index.js
中的,而目前是参考WebStorm
创建的工程,除了index.js
还有App.js
,会报错,修改
export default class RNHighScores extends React.Component {
<2> 获取变量的方法可以用{}
<3>
When you build a React Native application, you use the React Native packager to create an index.bundle that will be served by the React Native server. Inside index.bundle will be our RNHighScore module. So, we need to point our RCTRootView to the location of the index.bundle resource (via NSURL) and tie it to the module.
如果在真机的环境下,要替换成对应的mac
(服务器)的IP
<4> 要保证
package.json
,moduleName:
后面的参数AppRegistry.registerComponent(appName, () => App);
cat package.json
{
"name": "AnNativeApp",// <= 这里
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "^16.6.3",
"react-native": "^0.58.5"
}
}
## import {name as appName} from './app.json';
cat app.json
{
"name": "AnNativeApp", <= 这里
"displayName": "AnNativeApp"
}%
这三者是一致的
<5> RCTRootView
继承自UIView
,要设置frame