Как предотвратить циклическую ссылку, когда соединительный заголовок Swift импортирует файл, который импортирует сам Hopscotch-Swift.h
Я интегрирую Swift в большой существующий проект Objective C и столкнулся с тем, что я считаю круговой ссылкой.
Рассматриваемые классы следующие:
Objective C Controller
#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?
5 ответов
Форвардная декларация должна работать, в вашем случае.
В вашем.h:
@protocol MyProtocol;
@interface MyController : UIViewController<MyProtocol>
@end
В вашем.m:
#import "HopScotch-Swift.h"
Как я могу добавить прямые ссылки на классы, используемые в заголовке -Swift.h? и руководство по совместимости Swift:
Если вы используете свои собственные типы Objective C в своем коде Swift, обязательно импортируйте заголовки Objective C для этих типов, прежде чем импортировать сгенерированный заголовок Swift в файл Objective C, из которого вы хотите получить доступ к коду Swift.
Я столкнулся с этим, когда пытался использовать классы 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
Предварительная декларация сама по себе не сработала. Он скомпилирован без ошибок, но все еще имел предупреждения, что протокол не может быть найден. Я воспринимаю все предупреждения как ошибки, так что этого недостаточно.
Я смог это исправить, переместив реализацию протокола в заголовок другой категории.
Вот что сработало для меня:
В моем 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"
В качестве альтернативы вы можете преобразовать свой протокол в протокол Objective-C, а затем использовать его в Swift, включивMyProtocol.h
в вашем связующем заголовке.
Вы можете что-то вроде этого в файле.h, который вы подозреваете, вызвать циклическую ссылку:
#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif