纯在 Swift 中的 React Native 应用程序
Posted
技术标签:
【中文标题】纯在 Swift 中的 React Native 应用程序【英文标题】:React Native app purely in Swift 【发布时间】:2016-10-17 07:48:31 【问题描述】:我使用以下命令创建了我的第一个 react 原生应用。
react-native init PropertyFinder
这为 Objective-C 中的 ios 创建了一个项目。问题是我不懂 Objective-C,但我在 Swift 上工作。
gist 展示了如何将 react-components 链接到 swift 项目。 但是有没有办法直接用 Swift 语言创建项目?
【问题讨论】:
【参考方案1】:这个excellent post 帮我解决了问题。
解决方案
添加桥接头
#import "RCTBridgeModule.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTRootView.h"
#import "RCTUtils.h"
#import "RCTConvert.h"
添加 AppDelegate.Swift
var bridge: RCTBridge!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
// Override point for customization after application launch.
/**
* Loading javascript code - uncomment the one you want.
*
* OPTION 1
* Load from development server. Start the server from the repository root:
*
* $ npm start
*
* To run on device, change `localhost` to the IP address of your computer
* (you can get this by typing `ifconfig` into the terminal and selecting the
* `inet` value under `en0:`) and make sure your computer and iOS device are
* on the same Wi-Fi network.
*/
let jsCodeLocation = NSURL(string: "http://localhost:8081/index.ios.bundle?platform=ios&dev=true")
/**
* OPTION 2
* Load from pre-bundled file on disk. The static bundle is automatically
* generated by "Bundle React Native code and images" build step.
*/
// jsCodeLocation = NSBundle.mainBundle().URLForResource("main", withExtension: "jsbundle")
let rootView = RCTRootView(bundleURL:jsCodeLocation as URL!, moduleName: "PropertyFinder", initialProperties: nil, launchOptions:launchOptions)
self.bridge = rootView?.bridge
self.window = UIWindow(frame: UIScreen.main.bounds)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window!.rootViewController = rootViewController;
self.window!.makeKeyAndVisible()
return true
删除AppDelegate.h
、AppDelegate.m
和主文件。
清理并构建您的项目。
【讨论】:
我试过这个。 RN 0.42;应用程序编译并运行正常,但是 Xcode 项目永远找不到 AppDelegate.swift 文件。模拟器显示黑屏。 我认为这些文件可能没有添加到Project
。选择Appdelegate file
并签入文件File inspector
,如果在Target Membership
下检查了您的项目名称。如果这些文件甚至没有在 Xcode 中显示,那么你应该搜索 _Add files to Xcode project_
此答案已过时。不要使用这个【参考方案2】:
如果您在导入时遇到问题
#import "RCTBridgeModule.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTRootView.h"
#import "RCTUtils.h"
#import "RCTConvert.h"
试试
#import <React/RCTBridgeModule.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTRootView.h>
#import <React/RCTUtils.h>
#import <React/RCTConvert.h>
【讨论】:
【参考方案3】:这实际上对我有用:
import Foundation
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
let jsCodeLocation: URL
jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index.ios", fallbackResource:nil)
let rootView = RCTRootView(bundleURL: jsCodeLocation, moduleName: "REPLACE_WITH_YOUR_PROJECT_NAME", initialProperties: nil, launchOptions: launchOptions)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
【讨论】:
注意:如果您在使用此@UIApplicationMain
宏时遇到错误提示“创建多个应用程序”,您可以尝试手动编写宏的实现:***.com/a/50750540/5951226【参考方案4】:
1) 在 Xcode 中打开 Worksapce 项目
2) 删除这些文件:
AppDelegate.h AppDelegate.m main.m3) 创建一个名为 AppDelegate 的新 Swift 文件,然后单击创建桥接头
4) 在 AppDelegate.swift 中复制以下内容
import Foundation
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
let jsCodeLocation: URL
jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index.ios", fallbackResource:nil)
let rootView = RCTRootView(bundleURL: jsCodeLocation, moduleName: "REPLACE_WITH_YOUR_PROJECT_NAME", initialProperties: nil, launchOptions: launchOptions)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
5) 将以下代码复制到桥接头文件中
#import "React/RCTBridgeModule.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "React/RCTRootView.h"
#import "React/RCTUtils.h"
#import "React/RCTConvert.h"
#import "React/RCTBundleURLProvider.h"
6) 立即运行您的项目
【讨论】:
这种方法在 2021 年有效,但我不得不将forBundleRoot: "index.ios"
更改为“索引”。另外,不要忘记添加您的模块名称!【参考方案5】:
我研究了一下,react-native
不支持该功能。
react-native init
正在做的是获取一个模板并更改其中的一些属性。
模板是用 Objective-C 编写的,所以除了手动修改结果之外,您无能为力。
但是,这不应该让您真正关心。你甚至可以在 Objective-C 项目中使用 Swift。无需将文件重写为 Swift。
【讨论】:
是的,最终我想通了。我主要关心的是用 Obj-C 编写的 AppDelegate 文件。所以,我用 swift 版本替换了那些,它开始工作了。我实际上错过了桥接头。感谢您的帮助顺便说一句(y)【参考方案6】:这对我有用:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate
func sourceURL(for bridge: RCTBridge!) -> URL!
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackResource:nil)
#else
return Bundle.main.url(forResource:"main", withExtension:"jsbundle")
#endif
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
self.bridge = RCTBridge(delegate: self, launchOptions: launchOptions)
let rootView = RCTRootView(bridge: self.bridge, moduleName: "SolutoPartnersApp", initialProperties: nil)
self.window = UIWindow(frame: UIScreen.main.bounds)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window!.rootViewController = rootViewController;
self.window!.makeKeyAndVisible()
return true
func applicationWillResignActive(_ application: UIApplication)
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
func applicationDidEnterBackground(_ application: UIApplication)
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
func applicationWillEnterForeground(_ application: UIApplication)
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
func applicationDidBecomeActive(_ application: UIApplication)
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
func applicationWillTerminate(_ application: UIApplication)
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
【讨论】:
以上是关于纯在 Swift 中的 React Native 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
如何解决 NSScanner 上的“架构 x86_64 的未定义符号”? react-native 中的 Swift pod
在我的 react-native 应用程序中的 Swift 中编译器生成的崩溃
如何从 react native 调用 swift native 函数?
将现有的移动应用程序从 Android Native(Java) 和 IOS Native(Swift) 迁移到 React Native