如何使 Swift class 符合 Objective-C 协议,而不将其暴露给 Objective-C?

How to make Swift class conform to Objective-C protocol, without exposing it to Objective-C?

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

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

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

确实会使用它

问题如下。我最终通过以下方式将 top-level Swift classes 导入 Objective-C:

#import "MyProject-Swift.h"

这会导致生成的 MyProject-Swift.h 文件出现 compile-time 错误,内容为:

找不到 'ASAuthorizationControllerDelegate' 的协议声明;你是说 'UINavigationControllerDelegate'?

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

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

的任何地方导入它

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

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

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

您可以创建一个实际符合 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 设为嵌套的 class,它无法公开给 Objective-C。

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

最简单的方法是添加

#import <AuthenticationServices/AuthenticationServices.h>

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