转换为 Swift 3 重命名了我自己的 Objective-C 方法
Posted
技术标签:
【中文标题】转换为 Swift 3 重命名了我自己的 Objective-C 方法【英文标题】:Converting to Swift 3 renamed my own Objective-C method 【发布时间】:2016-10-20 14:21:55 【问题描述】:我在我的 Objective-C 代码中混合了 swift 类。使用 Swift 2.3,一切都很好并且按预期工作。
我最近转换到 Swift 3,它更新了几个 API 调用,因为 Swift 3 发生了所有重命名。我明白了。
但不好的是,Swift 3 似乎已经重命名了 my Objective-C 类之一中的方法。我拥有 Objective-C 类,我调用了我想要的方法:readDeliveryInfoItems
。但是现在,在转换为 Swift 3 之后,我不能在我的 Swift 类中再调用 .readDeliveryInfoItems()
了。它告诉我它已重命名为.readItems()
。
这没有任何意义。而且Objective-C类仍然调用方法readDeliveryInfoItems
,所以这里有一些秘密。
我尝试将 Objective-C 的 readDeliveryInfoItems
方法重命名为 readDeliveryInfo
,构建(Swift 失败,因为它说 readInfo()
方法不存在,这很好),然后将方法重命名为readDeliveryInfoItems
。但是,当我在此之后构建时,Swift 又回到认为该方法称为 readInfo()
。我希望这会诱使 Xcode 刷新 Swift 桥接并将方法重命名为正确的名称 readDeliveryInfoItems()
,但它没有。
我该如何解决这个问题?
更新以添加更多信息
我的 Objective-C 类的接口有这个函数声明:
- (nullable NSArray<XMPPDeliveryInfoItem *> *)readDeliveryInfoItems;
但是在该类的 Generated Interface(见下面 MartinR 的评论)中,函数声明是这样的:
open func readItems() -> [XMPPDeliveryInfoItem]?
该类中还有其他类似readDeliveryInfoItems
函数的函数,比如这个:
- (nullable NSArray<XMPPDeliveryInfoItem *> *)sentDeliveryInfoItems;
它们在生成的界面中看起来是正确的:
open func sentDeliveryInfoItems() -> [XMPPDeliveryInfoItem]?
所以我无法弄清楚为什么我只有一个功能会遇到这个问题。
【问题讨论】:
您可以使用NS_SWIFT_NAME
来控制Swift 名称映射,参见例如以***.com/questions/39203235/… 为例。
Swift 3 编译器不会更改您的 Objective-C 文件中的任何内容,它仅适应 Swift 方面的 Swift 3 命名约定。
@MartinR 谢谢……是的,这行得通……但在这种情况下,我真的不想为这种方法这样做,而且我绝对不认为我应该这样做到。
无论如何,看看 ObjC 接口和 Swift 映射的(最小)自包含示例会很有帮助。
您可以查看 C/Objective-C 标头的“生成的接口”,请参阅developer.apple.com/library/content/qa/qa1914/_index.html 以获取说明。
【参考方案1】:
翻译过程在
中有详细描述 SE-0005 Better Translation of Objective-C APIs Into Swift与您的问题相关的部分是(强调我的):
从方法的基本名称中删除封闭类型的匹配项,以便 只要匹配开始于动词之后。例如,
extension UIViewController func dismissViewControllerAnimated(flag: Bool, completion: (() -> Void)? = nil)
变成:
extension UIViewController func dismissAnimated(flag: Bool, completion: (() -> Void)? = nil)
据我所知,这种修剪算法在 StringExtras.cpp(并使用了很多启发式方法), 和PartsOfSpeech.def 包含被视为动词的单词列表,例如
VERB(dismiss)
VERB(read)
VERB(send)
但不是VERB(sent)
。这就解释了为什么——稍微简化你的例子——
@interface DeliveryInfo : NSObject
-(void)readDeliveryInfoItems;
-(void)sentDeliveryInfoItems;
@end
变成
open class DeliveryInfo : NSObject
open func readItems()
open func sentDeliveryInfoItems()
类型名称在动词“read”之后被删减,但不在
非动词“发送”。 (您可以通过更改第二种方法来验证
名称为sendDeliveryInfoItems
,然后映射到sendItems()
。)
您可以使用NS_SWIFT_NAME
覆盖映射:
-(void)readDeliveryInfoItems NS_SWIFT_NAME(readDeliveryInfoItems());
【讨论】:
编译器无法判断您的意思是“阅读”(动词 to read 的过去分词)而不是主动动词。愚蠢的英语使那个词的时态相同...;)+1NS_SWIFT_NAME
如果您想保留“read”的较长结构或“sent”的较短结构。
@rickster: 显然编译器没有仔细listen,“read”和“read”的发音不一样吗?
好点。你应该提交一个错误......我敢打赌Apple的可访问性人员会想要正确处理它。到那时,我想解决方法是对所有标识符使用 IPA。
@MartinR 非常感谢您提供的信息...非常有用。【参考方案2】:
粗略地说(我过于简单化了),如果方法名称上的后缀是与返回类型匹配的动词对象,则删除后缀。
一个更简单的例子是一个名为 readString
的方法,它返回一个 NSString。
您的方法属于这些参数范围内(我告诉过您我过于简单,但您可以粗略地看到这是如何正确的),所以您得到了治疗。
就我个人而言,我认为这是一个错误,特别是因为在某些情况下,更改可能会导致名称冲突并使调用方法不可能(尤其是当 Objective-C API 不是你的并且你不能改变它)。举个例子,看看这个问题:Swift 3 (Omit Needless Words) causing two functions to have the same name
【讨论】:
以上是关于转换为 Swift 3 重命名了我自己的 Objective-C 方法的主要内容,如果未能解决你的问题,请参考以下文章
PromiseKit 3 for Swift2 中的“when”是不是已重命名?
将图像从 URL 保存到库,重命名并使用 Swift 共享它
更新到 Swift 3 破坏了我的 swifty json 代码