尝试理解 NS_REFINED_FOR_SWIFT 在整个类上的使用。

huangapple go评论82阅读模式
英文:

Trying to understand NS_REFINED_FOR_SWIFT when used on a whole class

问题

我正在处理一个使用Objective-C编写的框架项目。我试图确保最终的公共Swift API 遵循现代标准。因此,我正在研究诸如 NS_SWIFT_NAMENS_REFINED_FOR_SWIFT 等宏。我已经查阅了苹果的Objective-C和C代码自定义文档。但是他们只提供了一个使用 NS_REFINED_FOR_SWIFT 的示例,而且只是在方法级别。

我正好在查看CloudKit框架中的一些苹果头文件,特别是与新的 CKSyncEngine 相关的类型。我注意到每个Objective-C类都以 NS_REFINED_FOR_SWIFT 作为前缀。由于现在每个类名和方法名都隐藏在双下划线前缀之后,我想这意味着不仅有一个简单的Swift类扩展来更好地映射方法和属性名称。

我需要帮助的是,当多个Objective-C类都标记为 NS_REFINED_FOR_SWIFT 时,需要在框架中提供什么样的Swift代码来正确公开这些精炼的类名?

让我们从一个看起来很像 UIButtonUIButton.Configuration 的示例开始。Objective-C头文件可能如下所示:

NS_REFINED_FOR_SWIFT
@interface MyButtonConfiguration: NSObject

@end

NS_REFINED_FOR_SWIFT
@interface MyButton: UIControl

- (instancetype)initWithConfiguration:(MyButtonConfiguration *)configuration NS_SWIFT_NAME(init(configuration:));

@end

这只是一个起点的极度简化示例。如果代码真的这么简单,我可以轻松地在类名上使用 NS_SWIFT_NAME 并完成。但是我正在尝试理解更复杂的API的起点。

我希望最终的Swift API 有类名 MyButtonMyButton.Configuration(就像嵌套的范围一样)。

如果我没有在整个类上使用 NS_REFINED_FOR_SWIFT,而只是一些方法/属性,那么我会添加类似以下的Swift代码:

extension MyButton {
    func someRefinedAPI() {
        __someOriginalAPI()
    }
}

但是在类级别使用 NS_REFINED_FOR_SWIFT 意味着 MyButton 在Swift中暴露为 __MyButton,而 MyButtonConfiguration 在Swift中暴露为 __MyButtonConfiguration。我需要在我的框架中添加什么Swift代码,才能将这些精炼的名称暴露为 MyButtonMyButton.Configuration

我尝试了以下内容:

typealias MyButton = __MyButton // 这个有效
typealias MyButton.Configuration = __MyButtonConfiguration // 在句点处出现错误:类型别名声明中预期的 '='

我打算在这些之后添加用于精炼方法和属性的类扩展,但我无法跨越类名的起始点。

那么,在类级别使用 NS_REFINED_FOR_SWIFT 时,如何将Objective-C类名转换为嵌套的Swift类型层次结构?

在我的实际框架中,将有需要在Swift中成为第三层嵌套类型的Objective-C类型。例如,将 UIButtonConfigurationSize 转换为 UIButton.Configuration.Size,例如。NS_SWIFT_NAME 似乎不接受具有3层名称的情况。

英文:

I am working on a framework project written in Objective-C. I'm trying to ensure the resulting public Swift API follows modern standards. As a result I'm looking into macros such as NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT. I've been through Apple's documentation for Objective-C and C Code Customization. But they only have one example using NS_REFINED_FOR_SWIFT and it's at the method level.

I happen to be looking at some of the Apple header files in the CloudKit framework, specifically for the new CKSyncEngine related types. I noticed that every Objective-C class is prefixed with NS_REFINED_FOR_SWIFT. Since now every class name and method name is hidden with the double-underscore prefix, I imagine that this means that there is more than just a simple Swift class extension to help better map the method and property names.

What I need help with is a starting example when several Objective-C classes are marked with NS_REFINED_FOR_SWIFT. What Swift code must be provided in the framework to properly expose those refined class names?

Let's start with an example that looks a lot like UIButton and UIButton.Configuration. The Objective-C header file might look like this:

NS_REFINED_FOR_SWIFT
@interface MyButtonConfiguration: NSObject

@end

NS_REFINED_FOR_SWIFT
@interface MyButton: UIControl

- (instancetype)initWithConfiguration:(MyButtonConfiguration *)configuration NS_SWIFT_NAME(init(configuration:));

@end

This is a greatly oversimplified example as a starting point. If the code was really this simple I could easily use NS_SWIFT_NAME on the class names and be done. But I'm trying to understand the starting point for a far more complicated API.

I want to end up with the Swift API having the class names MyButton and MyButton.Configuration (like a nested scope).

If I had not used NS_REFINED_FOR_SWIFT on the whole class, but just some method/properties, then I would add Swift code such as:

extension MyButton {
    func someRefinedAPI() {
        __someOriginalAPI()
    }
}

But having NS_REFINED_FOR_SWIFT at the class level means that MyButton is exposed as __MyButton and MyButtonConfiguration is exposed as __MyButtonConfiguration in Swift. What Swift code do I need to add to my framework to get those refined names exposed as MyButton and MyButton.Configuration?

I tried something like the following:

typealias MyButton = __MyButton // This works
typealias MyButton.Configuration = __MyButtonConfiguration // Gives error at the period with: Expected '=' in type alias declaration

I was going to follow those with the class extensions for the refined methods and properties but I can't get past the starting point of the class names.

So how do you translate an Objective-C classname into a nested Swift type hierarchy when using NS_REFINED_FOR_SWIFT at the class level?

In my real framework there will be Objective-C types that need to become 3rd level nested types in Swift. Think UIButtonConfigurationSize to UIButton.Configuration.Size, for example. NS_SWIFT_NAME doesn't seem to accept names with 3 levels.

答案1

得分: 1

NS_REFINED_FOR_SWIFT用于返回参数中的指针值的API方法。
经过改进的API将以元组形式返回值。

NS_REFINED_FOR_SWIFT无法创建嵌套类。

但您仍然可以编写:

extension MyButton {
    typealias Configuration = __MyButtonConfiguration
}
英文:

NS_REFINED_FOR_SWIFT is used for API's methods that return values by pointer in parameters.
Refined API will return values in tuple instead.

NS_REFINED_FOR_SWIFT can't create nested classes.

Still you can write:

extension MyButton {
    typealias Configuration = __MyButtonConfiguration
}

答案2

得分: 0

通过@Cy-4AH的指导,我找到了如何获得第三层的方法。

例如,如果我想要将Objective-C类MyButtonConfigurationSize在Swift中显示为MyButton.Configuration.Size,那么在添加第一个扩展之后,我需要:

extension MyButton.Configuration {
    typealias Size = __MyButtonConfigurationSize
}

现在看起来似乎是如此明显。

英文:

With the push in the right direction by @Cy-4AH I figured out how to get a 3rd level as well.

For example, if I want the Objective-C class MyButtonConfigurationSize to be exposed as MyButton.Configuration.Size in Swift, then after adding the first extension, I would need:

extension MyButton.Configuration {
    typealias Size = __MyButtonConfigurationSize
}

It seems so obvious now.

huangapple
  • 本文由 发表于 2023年7月18日 02:12:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707092.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定