Как предотвратить циклическую ссылку, когда 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?
Ответы
Ответ 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