公开给 Objective-C 代码时 Swift 类的名称不遵守 @objc 重命名 [英] Name of Swift class when exposed to Objective-C code does not respect the @objc renaming

查看:25
本文介绍了公开给 Objective-C 代码时 Swift 类的名称不遵守 @objc 重命名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个像 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆