纯在 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.hAppDelegate.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.m

3) 创建一个名为 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 函数?

react-native ios中的网页抓取?

如何使用 Swift 创建 React-Native 框架

将现有的移动应用程序从 Android Native(Java) 和 IOS Native(Swift) 迁移到 React Native