xcode 公开给 Objective-C 代码时 Swift 类的名称不遵守 @objc 重命名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26132823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Name of Swift class when exposed to Objective-C code does not respect the @objc renaming
提问by Manav
Given a declaration of a Swift class like
给定一个 Swift 类的声明,如
@objc(NSFoo) public class Foo {
public func bar() -> () {}
}
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:
我希望,从我对文档的阅读来看,在 Objective-C 方面,我们将能够使用 identifier 来引用这个类NSFoo
。对我来说,这似乎不是正在发生的事情。生成的定义ProjectName-Swift.h
是:
SWIFT_CLASS("NSFoo")
@interface Foo
- (void)bar;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
whereas what I would expect is
而我期望的是
SWIFT_CLASS("Foo")
@interface NSFoo
...
I am using Xcode 6.0.1.
我正在使用 Xcode 6.0.1。
I missing something, or is this just a Xcode bug?
我遗漏了什么,或者这只是一个 Xcode 错误?
回答by milos
Note: Things have change since this answer was first written - see updates at the end!
注意:自从首次编写此答案以来,情况发生了变化 - 请参阅最后的更新!
Yeah, this does seam to be a bug... though, controlling Obj-C runtime names of methods does work:
是的,这确实是一个错误......不过,控制方法的 Obj-C 运行时名称确实有效:
Say we define a pair of minimal Obj-C and Swift classes that interact with each other:
假设我们定义了一对相互交互的最小 Obj-C 和 Swift 类:
Foo.swift
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
NSBar.h
#import <Foundation/Foundation.h>
@interface NSBar : NSObject
+ (NSString *)postcard;
+ (void)getMail;
@end
NSBar.m
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
If we now call their class methods, say, from main.m
:
如果我们现在调用它们的类方法,比如说,来自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);
}
This prints the following:
这将打印以下内容:
// --> Printed in Swift: Postcard from Objective C!
// --> Printed in Objective C: Postcard from Swift!
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!
但它不应该有!Foo
应该只对 Obj-C 可见,SwiftFoo
因为这@objc(SwiftFoo)
是有前途的。实际上,使用SwiftFoo
会触发Use of undeclared identifier
编译器错误。事实上,这确实适用于方法名称,毫无疑问这是一个错误。我很惊讶你似乎是第一个提出这个问题的人!加一个!
And yes:
是的:
// <#ModuleName#>-Swift.h
SWIFT_CLASS("SwiftFoo")
@interface Foo
+ (NSString *)postcardFromSwift;
+ (void)getMailInSwift;
... 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.
...确实要为类名反转接缝,但这就是该宏的工作方式 - 请参阅 WWDC 视频Swift 互操作性深入(视频中大约45 分钟和 48 分钟)。相关文档是在 Objective-C 中公开 Swift 接口。
Xcode 7 beta 4
Xcode 7 测试版 4
The issue is now fixed (thanks to @ScottBerrevoets for the comment).
该问题现已修复(感谢@ScottBerrevoets 的评论)。
Xcode 7.1
Xcode 7.1
(thanks to @Pang for the comment)
(感谢@Pang 的评论)
@objc class C { } // error: only classes that inherit from NSObject can be declared @objc
回答by mkirk
Currently (in XCode8) this seems to have been addressed.
目前(在 XCode8 中)这似乎已得到解决。
Defined in XYZLogger.h and XYZLogger.m
在 XYZLogger.h 和 XYZLogger.m 中定义
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Logger)
@interface XYZLogger : NSObject
+ (void)verbose:(NSString *)logString;
+ (void)debug:(NSString *)logString;
+ (void)info:(NSString *)logString;
+ (void)warn:(NSString *)logString;
+ (void)error:(NSString *)logString;
@end
NS_ASSUME_NONNULL_END
Used in objc like this:
像这样在 objc 中使用:
[XYZLogger debug:@"Hi from objective C"];
Used in Swift like this:
像这样在 Swift 中使用:
Logger.debug("Hi from swift");