公开给 Objective-C 代码时 Swift 类的名称不遵守 @objc 重命名 [英] Name of Swift class when exposed to Objective-C code does not respect the @objc renaming
问题描述
给定一个像 Swift 类的声明
Given a declaration of a Swift class like
@objc(NSFoo) public class Foo {
public func bar() -> () {}
}
我希望,从我阅读的文档来看,在 Objective-C 方面,我们可以使用标识符 NSFoo
来引用这个类.对我来说,这似乎不是正在发生的事情.ProjectName-Swift.h
中生成的定义是:
I would expect, from my reading of the documentation, that on the Objective-C side of things we would be able to refer to this class using the identifier NSFoo
. This is not what seems to be happening for me. The generated definition in ProjectName-Swift.h
is:
SWIFT_CLASS("NSFoo")
@interface Foo
- (void)bar;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
而我期望的是
SWIFT_CLASS("Foo")
@interface NSFoo
...
我使用的是 Xcode 6.0.1.
I am using Xcode 6.0.1.
我遗漏了什么,或者这只是一个 Xcode 错误?
I missing something, or is this just a Xcode bug?
推荐答案
注意:自从第一次写这个答案以来,事情已经发生了变化 - 请参阅最后的更新!
是的,这确实是一个错误......不过,控制方法的 Obj-C 运行时名称确实有效:
Yeah, this does seam to be a bug... though, controlling Obj-C runtime names of methods does work:
假设我们定义了一对相互交互的最小 Obj-C 和 Swift 类:
Say we define a pair of minimal Obj-C and Swift classes that interact with each other:
Foo.swift
import Foundation
@objc(SwiftFoo)
class Foo { // inheriting from NSObject makes no difference in this case
@objc(postcardFromSwift)
class func postcard() -> String {
return "Postcard from Swift!"
}
@objc(getMailInSwift)
class func getMail() {
if let hello = NSBar.postcard() { // NSBar is an Obj-C class (see below)
println("Printed in Swift: \(hello)")
}
}
}
NSBar.h
#import <Foundation/Foundation.h>
@interface NSBar : NSObject
+ (NSString *)postcard;
+ (void)getMail;
@end
NSBar.m
#import "NSBar.h"
#import "ObjS-Swift.h"
@implementation NSBar
+ (void)getMail {
// notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo)
printf("Printed in Objective C: %s", [[Foo postcardFromSwift] UTF8String]);
}
+ (NSString *)postcard {
return @"Postcard from Objective C!";
}
@end
如果我们现在从 main.m
调用它们的类方法:
If we now call their class methods, say, from main.m
:
#import <Cocoa/Cocoa.h>
#import "NSBar.h"
#import "ObjS-Swift.h"
int main(int argc, const char * argv[]) {
// notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo)
[Foo getMailInSwift];
[NSBar getMail];
return NSApplicationMain(argc, argv);
}
这将打印以下内容:
// --> Printed in Swift: Postcard from Objective C!
// --> Printed in Objective C: Postcard from Swift!
但它不应该有!Foo
应该只对 Obj-C 作为 SwiftFoo
可见,因为这是 @objc(SwiftFoo)
承诺做的.实际上,使用 SwiftFoo
会触发 Use of undeclared identifier
编译器错误.事实上,这确实适用于方法名称,毫无疑问这是一个错误.我很惊讶你似乎是第一个提出这个问题的人!再加一个!
But it shouldn't have! Foo
should only be visible to Obj-C as SwiftFoo
since that is what @objc(SwiftFoo)
is promising to do. Indeed, using SwiftFoo
triggers the Use of undeclared identifier
compiler error instead. The fact that this did work for method names, leaves little doubt that this is a bug. I am just amazed that you seem to be the first to ask about it! Plus one for that!
是的:
// <#ModuleName#>-Swift.h
SWIFT_CLASS("SwiftFoo")
@interface Foo
+ (NSString *)postcardFromSwift;
+ (void)getMailInSwift;
... 确实要为类名反转接缝,但这就是该宏的工作方式 – 参见 WWDC 视频 深入 Swift 互操作性(视频中大约 45 分钟和 48 分钟).相关文档是 在 Objective-C 中暴露 Swift 接口.
... does seam to be inverted for the class name, yet this is how that macro works – see WWDC video Swift Interoperability In Depth (c. 45 min and c. 48 min into the video). The relevant documentation is Exposing Swift Interfaces in Objective-C.
Xcode 7 测试版 4
问题现已解决(感谢@ScottBerrevoets 的评论).
The issue is now fixed (thanks to @ScottBerrevoets for the comment).
Xcode 7.1
(感谢@Pang 的评论)
(thanks to @Pang for the comment)
@objc class C { } // error: only classes that inherit from NSObject can be declared @objc
这篇关于公开给 Objective-C 代码时 Swift 类的名称不遵守 @objc 重命名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!