英文:
Trying to understand NS_REFINED_FOR_SWIFT when used on a whole class
问题
我正在处理一个使用Objective-C编写的框架项目。我试图确保最终的公共Swift API 遵循现代标准。因此,我正在研究诸如 NS_SWIFT_NAME
和 NS_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代码来正确公开这些精炼的类名?
让我们从一个看起来很像 UIButton
和 UIButton.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 有类名 MyButton
和 MyButton.Configuration
(就像嵌套的范围一样)。
如果我没有在整个类上使用 NS_REFINED_FOR_SWIFT
,而只是一些方法/属性,那么我会添加类似以下的Swift代码:
extension MyButton {
func someRefinedAPI() {
__someOriginalAPI()
}
}
但是在类级别使用 NS_REFINED_FOR_SWIFT
意味着 MyButton
在Swift中暴露为 __MyButton
,而 MyButtonConfiguration
在Swift中暴露为 __MyButtonConfiguration
。我需要在我的框架中添加什么Swift代码,才能将这些精炼的名称暴露为 MyButton
和 MyButton.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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论