Swift认为我错误地继承了NSSet,但我根本没有继承它

uli*_*ess 8 objective-c objective-c++ ios swift swift5

我从Swift编译器收到一个奇怪的错误消息:

<unknown>:0: error: 'required' initializer 'init(arrayLiteral:)' must be provided by subclass of 'NSSet'
Foundation.NSSet:2:33: note: 'required' initializer is declared in superclass here
    required public convenience init(arrayLiteral elements: Any...)
                                ^
Run Code Online (Sandbox Code Playgroud)

请注意,我的代码都没有子类化NSSet(nor Set。所以我不知道为什么斯威夫特认为我在做这件事,更不用说错误了。

我的项目有点特别,因为我有一些Objective-C类(通过Objective-C调用C ++代码)和一个module.map文件,可以让Swift调用C库。

编译Swift文件时发生错误(我是从几个Swift文件中获得的,但是只有其中一些使用C库,但是到目前为止,所有这些似乎都在与ObjC类进行对话)。如您所见,Swift没有错误的行号,尽管有人在继承NSSet。

有人看过吗?有谁知道如何诊断这个问题?我尝试注释掉部分代码,但似乎找不到任何有助于跟踪此问题的内容。

要强调的是:我没有做NSSet的任何子类化。我认为我什至没有在代码中使用NSSet。这就是Swift编译器似乎正在弥补的问题。

更新: 另一个问题使我想到,它可能与从Class对象实例化实例有关。我有一个Class我稍后要实例化的类:

@interface MYInfo : NSObject

@property Class myClass;

@end

Run Code Online (Sandbox Code Playgroud)

后来我使用Swift中的实例化它:

guard let myClass = info.myClass.init() as? MyClass else { return }
Run Code Online (Sandbox Code Playgroud)

如果我删除了这最后一行,错误消息就会消失。

uli*_*ess 8

因此想出了这个,这要归功于另一个问题(尽管这是完全不同的):

  1. 当您尝试初始化一个类型为ObjC Class类型的变量时,'required' initializer 'init(arrayLiteral:)' must be provided by subclass of 'NSSet'即使不涉及NSSet,Swift编译器还是非常愚蠢的。我猜NSSet是它知道的第一个或最后一个ObjC init方法。

  2. Swift编译器还会在随机源文件(甚至是空文件)上显示此错误,这是因为Swift解析项目中所有其他文件的“神奇”方式,因此您可以引用它们中的类而无需include像C这样的语句。

  3. 实例化a的正确方法Class是首先进行类型转换:

guard let myClass = info.myClass as? (NSObject & MyClass).Type else { return }
let myInstance = myClass.init()
Run Code Online (Sandbox Code Playgroud)

这比原来更难弄清楚。