Подтвердить что ты не робот

Как предотвратить циклическую ссылку, когда Swift-заголовок заголовка импортирует файл, который импортирует сам Hopscotch-Swift.h

Я интегрирую Swift в большой существующий проект Objective C и столкнулся с тем, что я считаю круговой ссылкой.

Рассматриваемые классы следующие:

Контроллер Objective C

#import "Hopscotch-Swift.h"

@interface MyController : UIViewController<MyProtocol>
   ...
@end

Быстрый протокол

@objc protocol MyProtocol: NSObjectProtocol {
   ...
}

Заголовок моста

#import "MyController.h"

Этот код не скомпилируется, потому что файл Hopscotch-Swift.h не будет сгенерирован.

Я думаю, что это связано с циклической ошибкой ссылки, так как я могу импортировать Hopscotch-Swift.h в объектные заголовки c, которые не включены в Hopscotch-Bridging-Header.h, и он отлично работает.

Есть ли обходной путь для этой проблемы или я должен подать радар с Apple?

4b9b3361

Ответ 1

Форвардное объявление должно работать в вашем случае.

В вашем .h:

@protocol MyProtocol;

@interface MyController : UIViewController<MyProtocol>

@end

В вашем .m:

#import "HopScotch-Swift.h"

От Как добавить ссылки на прямые классы, используемые в заголовке -Swift.h? и руководство по оперативной совместимости Swift:

Если вы используете свои собственные типы Objective-C в своем коде Swift, обязательно импортируйте заголовки Objective-C для этих типов до импорта сгенерированного заголовка Swift в файл Objective-C.m, который вы хотите получить в Swift код от.

Ответ 2

Я столкнулся с этим при попытке использовать классы Swift внутри протоколов Objective-C, где протокол также был реализован другим классом Swift. Он вонял круговые ссылки, и я догадался, что это может быть проблема, пытающаяся циклически генерировать мостовые заголовки, а не "нормальную" циркулярную проблему.

Решение для меня заключалось в том, чтобы просто использовать форвардные объявления перед объявлением протокола: -

// don't include the MyProject-Swift.h header

// forward declaration of Swift classes used
@class SwiftClass;

@protocol MyProtocol <NSObject>
- (SwiftClass *)swiftClass;
@end

Ответ 3

Самостоятельное выражение само по себе не помогло мне. Он скомпилирован без ошибок, но все еще имел предупреждения о том, что протокол не найден. Я рассматриваю все предупреждения как ошибки, поэтому это недостаточно.

Я смог исправить это, переместив реализацию протокола в другой заголовок категории.

Так вот что сработало для меня:

В MyOtherSwiftFile.swift:

@objc protocol MyProtocol: class {
func viewController(didFinishEditing viewController: MyViewController)
}

В моем MyViewController.h:

@interface MyViewController // Removed protocol implementation declaration here
@end

Добавлен MyViewController + MyProtocol.h для создания проекта и добавьте его:

@interface MyViewController (MyProtocol) <MyProtocol>
@end

Сами методы могут оставаться там, где они есть, если хотите.

После того, как вы реализуете вышеизложенное и скомпилируете, вы получите предупреждение о компиляторе где-нибудь в своем коде, который требует, чтобы MyViewController реализовал MyProtocol. В этом файле вы будете #import "MyViewController+MyProtocol.h"

Ответ 4

Вы могли бы что-то подобное в файле .h, который вы подозреваете, чтобы вызвать круговую ссылку:

#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif