【问题标题】:How to make Swift class conform to Objective-C protocol, without exposing it to Objective-C?如何使 Swift 类符合 Objective-C 协议,而不将其暴露给 Objective-C?
【发布时间】:2020-11-19 22:53:35
【问题描述】:

我有一个名为 LoginCoordinator 的 Swift 类,它执行“使用 Apple 登录”请求。为了响应回调,它符合ASAuthorizationControllerDelegate。因为这个需求,我还需要把这个类变成NSObject的子类:

class LoginCoordinator: NSObject { ... }
extension LoginCoordinator: ASAuthorizationControllerDelegate { ... }

这个类根本不会被任何 Objective-C 类使用。它旨在供其他 Swift 类(即LoginViewController)使用,而这些类确实会被 Objective-C 类使用

问题如下。我最终通过以下方式将顶级 Swift 类导入到 Objective-C:

#import "MyProject-Swift.h"

这会在生成的MyProject-Swift.h 文件中导致编译时错误,该文件显示:

找不到“ASAuthorizationControllerDelegate”的协议声明;你的意思是“UINavigationControllerDelegate”吗?

此错误出现在生成的 Objective-C 类别对应的行上,该类别对应于我上面在 Swift 中编写的扩展,其中我使 LoginCoordinator 符合 ASAuthorizationControllerDelegate

如果在导入MyProject-Swift.h 之前,我还导入了<AuthenticationServices/AuthenticationServices.h>,那么错误就会消失。但我不想在我导入 Swift 的任何地方都导入它。

如果我理解正确,这是怎么回事:当我将我的 Swift 文件导入到 Objective-C 中时,它会将所有生成的标头导入到 MyProject-Swift.h 中。但是其中一个类别标头 (LoginCoordinator) 引用了尚未导入的协议 (ASAuthorizationControllerDelegate),这会引发错误。

我注意到MyProject-Swift.h 只是在我将LoginCoordinator 设为NSObject 的子类后才开始为它生成代码。删除子类化会删除生成的代码,但它当然不能符合协议。

有没有办法让 Swift 类成为 NSObject 的子类并符合 Objective-C 协议,而不在 Objective-C 中导入 Swift 文件时暴露它?

【问题讨论】:

  • 所以问题是你不想在MyProject-Swift.h之前到处导入AuthenticationServices?
  • 或者您可以将 LoginCoordinator 放在单独的模块中,并私下遵守ASAuthorizationControllerDelegate。您只需要导入该模块而不是导入 -Swift.h
  • @Cy-4AH 好主意。理想情况下,我想避免创建一个新模块,但如果我找不到其他方法,那么我可能会这样做。
  • 答案对我有用。如果它也对你有用,请接受它作为答案。

标签: objective-c swift nsobject bridging-header language-interoperability


【解决方案1】:

您可以创建一个实际符合 ASAuthorizationControllerDelegate 的私有对象,并将消息转发给 LoginCoordinator。很丑,但可以解决问题。

class LoginCoordinator {
    private lazy var authDelegate: LoginCordinatorASAuthorizationControllerDelegate {
        LoginCordinatorASAuthorizationControllerDelegate(coordinator: self)
    }
}

//MARK: functions from ASAuthorizationControllerDelegate, but not conforms it
extension LoginCoordinator {
    private func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization....)
}

private class LoginCordinatorASAuthorizationControllerDelegate: NSObject, ASAuthorizationControllerDelegate {
    weak var coordinator: LoginCoordinator!
    init(coordinator: LoginCoordinator)
}

你也可以让你的 LoginCoordinator 成为一个不能暴露给 Objective-C 的嵌套类。

enum Login {
    class Coordinator: NSObject, ASAuthorizationControllerDelegate {...}
}

【讨论】:

    【解决方案2】:

    最简单的方法是添加

    #import <AuthenticationServices/AuthenticationServices.h>

    到 Objective-C 桥接头 MyProject-Swift.h

    【讨论】:

    • 这不应该是认可的答案吗?
    • 不适合我
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    相关资源
    最近更新 更多