objective-c - programming - using bridging headers with framework targets is unsupported




Swift to Objective-C header non creato in Xcode 6 (20)

Recentemente ho lavorato per aggiungere Swift a un progetto esistente, per provarlo in un modo reale.

Dopo aver aggiunto un file sorgente Swift al progetto, non ho problemi a ottenere il "Bridging Header", cioè Objective-C a Swift.

Ma il file di intestazione -Swift.h che dovrebbe esporre le classi Swift o contrassegnate con @objc o sottoclassi di classi ObjC, non si trova da nessuna parte :-(

Non vedo alcuna istruzione specifica su come realizzare l'uso della mia nuova sottoclasse, scritta in Swift, nel mio codice app principale (che è ancora Obj-C).

L'app di cui sono uno sviluppatore principale ha una base di codice abbastanza grande (70.000 righe), quindi la transizione in una volta sola è fuori questione.


A volte hai solo bisogno di disinserire e quindi impostare nuovamente l'appartenenza di destinazione sul file obj-c .m.


Consentitemi di condividere le mie esperienze cercando di utilizzare Swift in un vecchio progetto objc. Non ho dovuto impostare il Defines module su YES .

Nel mio caso avevo bisogno di verificare manualmente che ci fosse un objc Bridging Header. Solo il nome dell'intestazione dell'interfaccia generata era presente nelle mie impostazioni di compilazione.

Questo ha portato alla creazione di un file MyApp-Swift.h, ma senza alcuna traccia delle mie classi Swift.

La documentazione Apple dice che ti verrà richiesto di creare un'intestazione di bridging quando aggiungi il tuo primo file swift. Beh, non lo ero. Ho aggiunto manualmente un file MyApp-Bridging-header.h e l' MyApp-Bridging-header.h indicato nel campo "Objective-C Bridging Header". Ciò ha reso il mio file MyApp-Swift.h popolato con le mie classi Swift.

Documenti: importazione di Swift in Objective-C


Ecco un'altra variante di moduleName-Swift.h che non viene generata.

Ho deciso di includere i grafici IOS nel mio progetto ma non volevo mescolare i sorgenti nella stessa directory, quindi ho posizionato la cartella del progetto Grafici accanto alla cartella del progetto del mio codice. Ho trascinato il progetto Charts nella barra di navigazione del mio progetto e incluso il framework nell'elenco Binari incorporati del target del progetto nelle impostazioni generali del progetto e ho impostato lo switch Swift Code di Embedded Content Contains su yes nella scheda Build Settings del progetto nella sezione Build Options .

Il file moduleName-Swift.h del mio progetto non verrebbe mai generato a prescindere da quali altri interruttori o impostazioni suggerissero qui. Infine, usando il metodo di Lou Z per cercare i file -Swift.h, ho visto che un file Charts-Swift.h veniva generato in profondità nella directory Build xcode del mio progetto in Charts.framework / Headers /

La soluzione per utilizzare il pacchetto Swift di ios-charts di Daniel Gindi senza includere il codice nella directory di origine del mio progetto era aggiungere:

#import "Charts/Charts-Swift.h"

Ai moduli che tracciano i dati del mio progetto.


Ho avuto lo stesso problema. Sembra che tu debba regolare le impostazioni (Definisci Modulo e Nome Modulo Prodotto) prima di aggiungere il tuo primo file Swift.

Se lo fai in seguito, il file "* -Swift.h" non verrà generato per questo progetto anche se aggiungi altri file Swift o se elimini il file Swift e ne crei uno nuovo.


Ho avuto un problema simile ma il mio progetto si stava compilando prima e improvvisamente ho avuto un errore dopo pochi cambiamenti al codice dei file. Mi ci è voluto un po 'per capire perché ottengo l'errore "File non trovato" per il file myproject-swift.h. Le modifiche al codice che avevo fatto avevano alcuni errori. Xcode non puntava invece quegli errori che mostravano sempre l'errore 'File not found'. Poi ho preso copia del codice della versione precedente e l'ho confrontato con il nuovo codice e unito i file uno per uno. Dopo l'unione di ciascun file, il progetto è stato trovato per trovare l'errore. Quindi la linea di fondo è se si ha un errore nel codice. Xcode potrebbe semplicemente visualizzare 'errore di file non trovato' per il file myproject-swift.h. Molto probabilmente hai errori di compilazione nel tuo progetto. Pulisci quegli errori e funzionerà.


Ho dovuto eliminare il codice Swift di WatchOS2 dal mio progetto Objective C. E solo dopo che XCode si è offerto di generare -Swift.h


Ho trovato questa soluzione

  • Crea SwiftBridge.h
  • metti #import "ProductModuleName-Swift.h"
  • Rendi pubblico questo file .h (importante) Seleziona il file -> In Mostra il File Inspector (barra destra) -> Rendi pubblico

Ora puoi

#import "SwiftBridge.h"

invece di ProductModuleName-Swift.h

Questa è una soluzione alternativa, per la prossima versione di Xcode penso che questo problema verrà risolto. In bocca al lupo


Ho trovato un trucco che funziona sempre su di me.

  1. Crea il tuo #import "ProductModuleName-Swift.h" nel tuo file appDelegate.h e nel tuo file ProductName-Prefix.pch. Se non lo hai in xcode 6 puoi crearlo in questo modo Perché non è ProjectName-Prefix.pch creato automaticamente in Xcode 6?
  2. Comando + Maiusc + k per pulire il tuo codice, se ricevi un errore sul tuo "ProductModuleName-Swift.h" cancellalo dal file appDelegate.h.
  3. Pulisci nuovamente il tuo codice. Ora tutto funzionerà come un fascino
  4. Se ricevi di nuovo un errore relativo a "ProductModuleName-Swift.h", ora crea di nuovo nel file appDelegate.h e ripulisci il tuo codice.

Fai questo lavoro (cancella e crea il "ProductModuleName-Swift.h" dal file appDelegate.h e pulisci il tuo codice) ogni volta che ricevi questo errore per silenziarlo.


Il progetto deve avere un Nome modulo che non include spazi. Definisce che il modulo deve essere impostato su Sì nelle impostazioni di creazione, in Packaging. ha commentato la dichiarazione #import:

Se continui ad avere errori nell'importazione di "ProductModuleName-Swift.h" allora

// # import "ProductModuleName-Swift.h"

che ha rivelato un sacco di altri errori nel mio codice Swift.

Una volta risolti questi nuovi errori e ottenuto il successo della creazione dei sorgenti, ho decommentato #import e bingo! L'intestazione è stata creata e importata correttamente :)


In secondo luogo ciò che molte persone hanno qui, ma aggiungendo una schermata pertinente. Il codice Swift e Obj-C può certamente vivere insieme. Non è un gioco tutto o niente.

Per accedere ai file Swift nel tuo Objective-C, tutto ciò che devi fare è aggiungere questa chiamata al tuo file Obj-C (nel file .m / implementation):

#import "{product_module_name}-Swift.h"

(Dove {product_module_name} rappresenta il nome del modulo del prodotto del tuo progetto). Piuttosto che cercare di indovinare il nome del modulo del prodotto o individuare casi angolari con spazi e caratteri speciali, basta andare alla scheda delle impostazioni di costruzione nel progetto e digitare "nome modulo prodotto" - l'ispettore ti rivelerà il tuo. Il mio era qualcosa che non mi aspettavo che fosse. Dai un'occhiata a questo screenshot se sei confuso.

E per far funzionare il codice Obj-c in Swift, devi solo aggiungere un file di intestazione di bridging e importare le intestazioni Obj-C rilevanti lì.


Nel mio caso ho dovuto impostare il target di implementazione almeno su "OS X 10.9" e l'intestazione -Swift.h stata generata automaticamente. Tenere presente che è possibile ricevere molti avvisi di deprecazione quando si modifica la versione di destinazione della distribuzione, in particolare se si dispone di una base di codice Objective C più vecchia e di grandi dimensioni. Nel nostro caso abbiamo anche avuto molto lavoro da fare nei file XIB e nelle classi di visualizzazione.


Ok, ecco tutte le cose di cui hai veramente bisogno!

1. Rimuovere tutti i file swift aggiunti e compilare il codice, senza errori.

----------

----------

2. Accedere alle impostazioni di creazione "Progetti" e impostare il nome del modulo del prodotto. Progetto deve avere un Nome modulo prodotto che non include spazi.

----------

----------

3.Sefines Module deve essere impostato su Yes in Build Settings, in Packaging, nel tuo progetto, e non target!

----------

----------

4. Ora crea un file rapido o un controller di visualizzazione, in file-> newFile->

----------

----------

Chiederà di creare un'intestazione di bridging, permettergli di crearne uno. Se lo hai rifiutato una volta, dovrai aggiungere manualmente un -Bridging-Header.h

5.Aggiungi @objc nel controller, per dire al compilatore che c'è un file rapido, che deve essere esposto a ObjectiveC

----------

----------

6. Costruisci il progetto e importa #import "-Swift.h" in uno qualsiasi dei controller objectiveC, e funzionerà! Puoi fare Command-click su di esso per vedere il file attuale!

----------

----------

Spero che questo ti aiuti!


Questa risposta affronta il caso d'uso in cui potresti già avere un codice Objective-C che chiama le classi Swift e quindi inizi a ricevere questo errore.

Come risolvere il problema

I seguenti passaggi alla fine hanno risolto tutti i problemi per me. Ho letto sopra qualcuno che menziona il "pollo e l'uovo" ed è esattamente quel concetto che mi ha portato a questa procedura. Questo processo esplicito mostra che è necessario rimuovere qualsiasi codice Objective-C che fa riferimento alle classi Swift fino a quando non viene generata l'intestazione.

  1. Commenta l'istruzione #import "ProductModuleName-Swift.h" nel tuo file di implementazione Objective-C
  2. Commenta qualsiasi riferimento nel file di implementazione Objective-C a Swift Classes
  3. Pulisci e crea
  4. Risolvi tutti gli errori / avvisi
  5. Rimuovi il commento sull'istruzione #import "ProductModuleName-Swift.h"
  6. Pulisci e crea (con successo o correggi eventuali errori rimanenti, verifica di non fare riferimento a nessuna classe Swift in Objective-C a questo punto .
  7. Verifica che "ProductModuleName-Swift.h" sia generato da Cmd-Cliccando sul nome della classe dell'istruzione #import "ProductModuleName-Swift.h"
  8. Rimuovi il commento sul codice che fa riferimento alle classi Swift nel file di implementazione Objective-C.
  9. Pulisci e costruisci normalmente (il "ProductModuleName-Swift.h" dovrebbe essere generato e il tuo codice Objective-C che fa riferimento a Swift Classes può essere usato normalmente)

Nota Bene: le risposte relative alla modifica degli spazi ai caratteri di sottolineatura e al modulo Definisci SÌ come indicato sopra si applicano ancora durante l'esecuzione di questo processo, così come le regole specificate nella documentazione Apple .

Bridging Header Path

In un errore, il file ProductModuleName-Bridging-Header.h non è stato trovato durante il processo di compilazione. Questo fatto ha generato un errore

<sconosciuto>: 0: errore: l'intestazione di bridging '/Users/Shared/Working/abc/abc-Bridging-Header.h' non esiste

Ispezione più ravvicinata dell'errore indica che il file non sarebbe mai esistito nella posizione descritta perché in realtà si trovava in ( percorso errato )

'/Users/Shared/Working/abc/abc/abc-Bridging-Header.h'. una rapida ricerca delle impostazioni di costruzione del target / progetto per effettuare la correzione manualmente e il file abc-Swift.h è stato nuovamente generato automaticamente.


Questo può essere un punto ovvio (forse troppo ovvio), ma è necessario avere almeno un file swift nel progetto per generare l'intestazione. Se stai scrivendo codice boilerplate o config con l'intenzione di scrivere rapidamente, l'importazione non funzionerà.


Se il nome del modulo del progetto contiene spazi, è necessario sostituire gli spazi con un carattere di sottolineatura.

Ad esempio, se il nome del tuo progetto è "Il mio progetto", dovresti usare:

#import "My_Project-Swift.h"


Se prima eri in grado di creare un progetto, senza problemi relativi a “ProductModuleName-Swift.h” not found , l'errore “ProductModuleName-Swift.h” not found , e ora stai ricevendo di nuovo quei brutti errori, la ragione potrebbe risiedere nelle tue recenti modifiche.

Per me questo era da (accidentale) errata codifica dei file .swift . Ripristinare le modifiche e riportare la parte posteriore manualmente, fa il lavoro.


Se stai usando qualcosa come Cocoapods (e stai lavorando fuori dallo spazio di lavoro piuttosto che dal progetto) prova ad aprire il progetto e a costruirlo prima di aprire lo spazio di lavoro e la costruzione. YMMV.


Solo un testa a testa per chi ha usato "." in là il nome del progetto. Xcode sostituirà il "." con un carattere di sottolineatura "_" per la versione Swift del file di intestazione del bridging. Stranamente, il Bridging-Header.h che viene generato non sostituisce i periodi con trattini bassi.

Ad esempio un progetto con il nome My.Project avrebbe i seguenti nomi di file di intestazioni di ponte.

Bridging-Header.h (Autogenerato)

My.Project-Bridging-header.h

Swift.h

My_Project.h

Spero che questo aiuti chiunque abbia usato un periodo e sia rimasto bloccato come me. Questo file può essere trovato nel seguente percorso.

Macintosh HD / Utenti / utente /Libreria/Developer/Xcode/DerivedData/My.Project-fntdulwpbhbbzdbyrkhanemcrfil/Build/Intermediates/My.Project.build/Debug-iphonesimulator/My.Project.build/DerivedSources

Stai attento,

Jon


Volevo aggiungere un altro motivo per cui potresti trovare un problema con questo: stavo creando un framework che mischiava il codice Swift e Objective-C. Non ero in grado di importare le classi Swift all'esterno del framework: ho controllato il file -Swift.h e veniva generato ma era vuoto.

Il problema si è rivelato molto, molto semplice: non avevo dichiarato pubblico alcun mio corso Swift! Non appena ho aggiunto la parola chiave pubblica alle classi, sono stato in grado di usarle da classi all'interno e all'esterno del framework.

Inoltre, all'interno del framework (all'interno dei file .m solo come un'altra risposta cita) ho dovuto importare il file -Swift.h come:

#import <FrameworkName/FrameworkName-Swift.h>

* L'unica cosa importante è: *

utilizzare il "Nome modulo prodotto" definito nella destinazione, seguito da -Swift.h

#import <Product Module Name>-Swift.h

// in each ObjectiveC .m file having to use swift classes
// no matter in which swift files these classes sit.

Non importa se il parametro "Definisci modulo" è impostato su Sì o No o se il progetto "Nome modulo prodotto" non è impostato.

Promemoria: le classi Swift devono derivare da NSObject o essere taggate con l'attributo @objc per essere esposte a ObjectiveC / Foundation || Cacao ...





swift