暴露于Objective-C代码时Swift类的名称不尊重@objc重命名

Man*_*nav 17 xcode swift

给出一个类似Swift类的声明

@objc(NSFoo) public class Foo {
   public func bar() -> () {}
}
Run Code Online (Sandbox Code Playgroud)

从我对文档的阅读中可以看出,在Objective-C方面,我们可以使用标识符来引用这个类NSFoo.这似乎不适合我.生成的定义ProjectName-Swift.h是:

SWIFT_CLASS("NSFoo")
@interface Foo
- (void)bar;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
Run Code Online (Sandbox Code Playgroud)

而我所期待的是

SWIFT_CLASS("Foo")
@interface NSFoo
...
Run Code Online (Sandbox Code Playgroud)

我正在使用Xcode 6.0.1.

我错过了什么,或者这只是一个Xcode错误?

mil*_*los 18

注意:自从这个答案首次编写以来,情况发生了变化 - 最后看到更新!

是的,这确实是一个错误...但是,控制方法的Obj-C运行时名称确实有效:

假设我们定义了一对彼此交互的最小Obj-C和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)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

NSBar.h

#import <Foundation/Foundation.h>

@interface NSBar : NSObject
+ (NSString *)postcard;
+ (void)getMail;
@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果我们现在调用他们的类方法,比如说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);
}
Run Code Online (Sandbox Code Playgroud)

这打印出以下内容:

// --> Printed in Swift: Postcard from Objective C!
// --> Printed in Objective C: Postcard from Swift!
Run Code Online (Sandbox Code Playgroud)

但它不应该有!Foo应该只对Obj-C可见,SwiftFoo因为这@objc(SwiftFoo)是有希望做的.实际上,使用SwiftFoo触发Use of undeclared identifier编译器错误.事实上,这确实适用于方法名称,这让人怀疑这是一个错误.我很惊讶您似乎是第一个提出这个问题的人!加一个!

是的:

// <#ModuleName#>-Swift.h
SWIFT_CLASS("SwiftFoo")
@interface Foo
+ (NSString *)postcardFromSwift;
+ (void)getMailInSwift;
Run Code Online (Sandbox Code Playgroud)

...为类名称设置了倒缝,但这就是宏的工作原理 - 参见WWDC视频Swift互操作性深度(约45分钟和约48分钟进入视频).相关文档是在Objective-C中公开Swift接口.

Xcode 7 beta 4

现在问题已解决(感谢@ScottBerrevoets的评论).

Xcode 7.1

(感谢@Pang的评论)

@objc class C { } // error: only classes that inherit from NSObject can be declared @objc
Run Code Online (Sandbox Code Playgroud)


mki*_*irk 5

目前(在 XCode8 中)这个问题似乎已经得到解决。

在 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
Run Code Online (Sandbox Code Playgroud)

在 objc 中使用如下:

[XYZLogger debug:@"Hi from objective C"];
Run Code Online (Sandbox Code Playgroud)

在 Swift 中使用如下:

Logger.debug("Hi from swift");
Run Code Online (Sandbox Code Playgroud)