Come evitare riferimenti circolari quando l’intestazione del bridging Swift importa un file che importa Hopscotch-Swift.h stesso

Sto integrando Swift in un grande progetto Objective C esistente e mi sono imbattuto in quello che penso sia un riferimento circolare.

Le classi in questione sono le seguenti:

Controller Objective C

#import "Hopscotch-Swift.h" @interface MyController : UIViewController ... @end 

Protocollo Swift

 @objc protocol MyProtocol: NSObjectProtocol { ... } 

Colpire l’intestazione

 #import "MyController.h" 

Questo codice non riesce a compilare perché il file Hopscotch-Swift.h non verrà generato.

Penso che questo sia dovuto ad un errore di riferimento circolare dato che posso importare Hopscotch-Swift.h in intestazioni obiettive c che non sono incluse in Hopscotch-Bridging-Header.h e funziona perfettamente.

C’è una soluzione alternativa per questo problema o dovrei presentare un radar con Apple?

La dichiarazione anticipata dovrebbe funzionare, nel tuo caso.

Nel tuo .h:

 @protocol MyProtocol; @interface MyController : UIViewController @end 

Nel tuo .m:

#import "HopScotch-Swift.h"

Da Come posso aggiungere i riferimenti alle classi utilizzati nell’intestazione -Swift.h? e la guida all’interoperabilità di Swift:

Se usi i tuoi tipi Objective-C nel tuo codice Swift, assicurati di importare le intestazioni Objective-C per quei tipi prima di importare l’intestazione generata da Swift nel file Objective-C .m da cui vuoi accedere al codice Swift.

Mi sono imbattuto in questo quando provavo ad usare le classi Swift all’interno dei protocolli Objective-C, dove il protocollo è stato implementato anche da un’altra class Swift. Puzzava di riferimenti circolari e ho intuito che potrebbe essere un problema cercare di generare circolarmente le intestazioni di bridging, piuttosto che un problema di inclusione circolare “normale”.

La soluzione, per me, era di usare solo dichiarazioni anticipate prima della dichiarazione del protocollo: –

 // don't include the MyProject-Swift.h header // forward declaration of Swift classs used @class SwiftClass; @protocol MyProtocol  - (SwiftClass *)swiftClass; @end 

La dichiarazione in avanti da sola non ha funzionato per me. Si è compilato senza errori ma ha ancora avvertito che il protocollo non è stato trovato. Tratto tutti gli avvertimenti come errori, quindi non è abbastanza buono.

Sono stato in grado di risolverlo spostando l’implementazione del protocollo in un’altra intestazione di categoria.

Quindi, ecco cosa ha funzionato per me:

Nel mio MyOtherSwiftFile.swift:

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

Nel mio MyViewController.h:

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

Aggiunto MyViewController + MyProtocol.h per la proiezione, e inseritelo qui:

 @interface MyViewController (MyProtocol)  @end 

I metodi stessi possono rimanere dove sono, se vuoi.

Dopo aver implementato quanto sopra e compilato, riceverai avvisi del compilatore da qualche parte nel tuo codice che richiede che MyViewController implementa MyProtocol . In quel file, #import "MyViewController+MyProtocol.h"

Si potrebbe qualcosa del genere nel file .h che si sospetta possa triggersre il riferimento circolare:

 #ifndef MY_HEADER_H #define MY_HEADER_H your header file #endif