【问题标题】:How to call Swift from an Objective C project App Delegate?如何从 Objective C 项目 App Delegate 调用 Swift?
【发布时间】:2021-04-27 11:11:34
【问题描述】:

此代码来自 Swift 项目 App 委托。它用于帮助使用可发布的密钥配置 Stripe。

//Appdelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: 
[UIApplicationLaunchOptionsKey: Any]?) -> Bool 
{
//The code helps configure Stripe with a publishable key.
STPPaymentConfiguration.shared().publishableKey = Constants.publishableKey
...
}

将 Swift 行添加到 Objective C App Delegate 后构建应用时显示两个错误

//AppDelegate.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
STPPaymentConfiguration.shared().publishableKey = Constants.publishableKey

Property 'shared' not found on object of type 'STPPaymentConfiguration'
Use of undeclared identifier 'Constants'

这是在将@objc 添加到演示 Swift 函数 MockApiClient 之前编译时出现的类似错误。它应该添加到其他地方吗?我已尝试将@objc 添加到此处的答案中提到的枚举中,但无济于事。

//Constants.swift 
//This is the file the original Swift app delegate accesses
import Foundation

  enum Constants {
  static let publishableKey = "pk_live_..."
  static let baseURLString = "http://54.33.123.227:1234"
  static let defaultCurrency = "usd"
  static let defaultDescription = "Receipt" //change to describe actual app & charge
  }

采取的步骤:

  1. 打开 Objective C 项目并创建一个桥接头

  2. 还在 Obj C 项目中时在 Swift 中创建了一个演示类,以确保它可以使用,在这种情况下,当视图加载时从 Objective C 文件中打印。具体派生自一个 NSObject。将覆盖添加到初始化程序并使用 @objc 前缀。

    //  MockApiClient.swift
    import Foundation
    class MockApiClient: NSObject
    {
    override init()
    {
    print("Initializer called in Mock API client")
    }
    @objc func executeRequest()
    {
    print("The execute request has been called in the Mock API Client")
    }
    }
    
    //ViewController.h
    //Prints the Swift request written in the MockApiClient the the view loads
    
    @implementation ViewController
    - (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    MockApiClient *client = [MockApiClient new];
    [client executeRequest];
    }
    
  3. #import "ViewController.h" 导入复制到自动生成的project-Bridging-Header.h 文件中,以便将其中的Objective C 公开给swift

  4. 将必要的 Swift 文件添加到 Objective C 项目,以便可以找到来自 Constants.swiftConstants.publishablekey 数据

如何将此 Swift App 委托代码添加到 Objective C 项目的 App 委托中?

编辑:将@objc 添加到Constants.swift 中的enum 声明时出错

【问题讨论】:

  • 如果 STPPaymentConfiguration 和 Constants 是 Swift 对象,那么要被 Objective-C 看到,它们需要是 Objective-C 可以 看到的类型(即用 @ 暴露的类987654337@),Objective-C文件需要导入自动生成的头文件(与“添加”头文件无关)。

标签: ios swift iphone xcode cocoa-touch


【解决方案1】:

编辑:将@objc 添加到 Constants.swift 中的枚举声明时出错

用作命名空间的 Swift 枚举不能暴露给 Objective-C。 您可能需要使用 class 使其同时适用于 Swift 和 Objective-C:

@objcMembers
class Constants: NSObject {
    static let publishableKey = "pk_live_..."
    static let baseURLString = "http://54.33.123.227:1234"
    static let defaultCurrency = "usd"
    static let defaultDescription = "Receipt" //change to describe actual app & charge
    
    private override init() {}
}

【讨论】:

  • 谢谢。按照建议更新Constants.Swift 文件后,Use of undeclared identifier 'Constants' 错误消失了,所以知道该应用程序似乎正在正式读取常量属性。现在只有一个错误Property 'shared' not found on object of type 'STPPaymentConfiguration'. Any ideas?
  • 委托中使用的STPPaymentConfiguration 类是在Stripe Cocoapods 中的STPPaymentConfiguration.h 中声明的。考虑到它已经用 Objective C 编写,如何进一步包含这个类?
  • 据我查看Stripe的文档页面,所有类型、属性和方法都已经标记为@objc。但是其中一些被赋予了独立于 Swift 名称的 Objective-C 名称。检查文档。
【解决方案2】:

Objective-C 查看 Swift 中定义的内容的能力取决于自动生成的头文件。这 不是 桥接头。它是一个隐藏在派生数据中的头文件,名为 YourProject-Swift.h。您的 Objective-C .m 文件需要 #import "YourProject-Swift.h"(使用正确的名称)。

然后,您的 Swift 内容需要进入该文件。为此,它们需要是 Objective-C 完全可以看到的类型(即类),并且需要使用适当的 @objc 属性显式地向 Objective-C 公开它们。

【讨论】:

  • 感谢@matt 的回复。您能否验证正确的步骤是创建一个桥接头,将#import "YourProject-Swift.h" 添加到 Appdelegate.m,将 #import "Stripe.h" 添加到桥接头文件,因为它包含一个包含所有 Stripe 头文件的 .m 文件,然后和AppDelegate.h 到桥接头文件中,然后在Appdelegate.m didFinishLaunchingWithOptions 方法中添加Swift 行,然后添加@objc 前缀?
  • 具体来说,我在 Constants.swift 中尝试过 @objc enum Constants... 并显示编译器警告:'@objc' enum must declare an integer raw type
  • 是的,你看我说的了吗?我很清楚Objective C可以看到什么。我提到枚举了吗?我说不是桥接头。请阅读我实际上所说的内容。
猜你喜欢
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 2016-10-30
  • 1970-01-01
  • 2015-01-24
  • 2018-12-05
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多