Свифт думает, что я неправильно подклассифицирую NSSet, но я не делаю его вообще - PullRequest
6 голосов
/ 24 апреля 2019

Я получаю странное сообщение об ошибке от компилятора 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...)
                                ^

Обратите внимание, что ни один из моего кода не имеет подклассов NSSet (или Set) . Так что я понятия не имею, почему Свифт думает, что я вообще это делал, не говоря уже о том, что ошибся.

Мой проект немного особенный, потому что у меня есть классы Objective-C, которые вызывают код C ++ (через Objective-C) и файл module.map, позволяющий Swift вызывать библиотеку C.

Ошибка возникает при компиляции файлов Swift (я получаю его из нескольких файлов Swift, но только некоторые из них используют библиотеку C, но все они до сих пор, похоже, общаются с классами ObjC). Как видите, Swift не имеет номера строки из-за своей ошибки, когда кто-то создает подкласс NSSet.

Кто-нибудь видел это? Кто-нибудь знает, как диагностировать эту проблему? Я пытался закомментировать биты кода, но я не могу найти ничего, что помогло бы отследить эту проблему.

Подчеркнуть: Я не делаю никаких подклассов NSSet. Я даже не использую NSSet в своем коде, я думаю. Это то, что компилятор Swift, кажется, только составляет.

Обновление: Другой вопрос дал мне идею, что это может быть связано с созданием экземпляра из объекта Class. У меня есть класс с Class, который я позже хочу создать:

@interface MYInfo : NSObject

@property Class myClass;

@end

Позже я использую это из Swift, чтобы создать его экземпляр:

guard let myClass = info.myClass.init() as? MyClass else { return }

Если удалить эту последнюю строку, сообщение об ошибке исчезнет.

1 Ответ

5 голосов
/ 24 апреля 2019

Так что понял, благодаря тому другому вопросу (который, однако, совсем другой):

  1. Swift Compiler ДЕЙСТВИТЕЛЬНО глуп, когда вы пытаетесь инициировать переменную, типизированную как Class типа ObjC, и выдает ошибочную ошибку 'required' initializer 'init(arrayLiteral:)' must be provided by subclass of 'NSSet', даже если NSSet не задействован. Я думаю, NSSet - это первый или последний метод инициализации ObjC, который он знает или что-то в этом роде.

  2. Компилятор Swift также показывает эту ошибку на случайных исходных файлах (даже пустых!) Из-за "волшебного" способа, которым Swift анализирует все другие файлы в проекте, чтобы вы могли ссылаться на классы в них без оператора include, как у C его есть.

  3. Правильный способ создания экземпляра Class - сначала ввести его:

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

Это было гораздо сложнее понять, чем следовало.

...