2014-06-07 9 views
8

Sto iniziando ad aggiungere file Swift a un progetto Objective-C molto grande e legacy che non utilizza ARC.Swift non è compatibile con pre-ARC Objective-C?

Quando compilo il progetto, ottengo gli avvertimenti per ogni proprietà emesso nell'intestazione ProjectName-Swift.h bridge:

  • No 'assegnare', 'trattenere', o è specificato l'attributo 'copia' - 'assegnare' è assunto
  • attributo proprietà default 'assegnare' non è appropriato per oggetto non GC

sembra Swift sta emettendo codice Objective-C ARC-based.

Si tratta di un limite/bug in questa particolare versione di Swift, oppure Swift è progettato per funzionare solo con il codice ARC?

+3

Non ho davvero idea del perché non stai ancora utilizzando ARC. Ho capito che è un codice legacy, ma il codice legacy dovrebbe essere aggiornato ... –

+0

l'era di "pre-ARC" chiamata 'MRC', forse è bello sapere cosa stai usando. – holex

+5

@LordZsolt Per evitare di introdurre inutilmente bug di gestione della memoria in una base di codice di grandi dimensioni che è stata ben testata nell'ambito del regime di gestione della memoria pre-ARC. – Bill

risposta

10

È possibile combinare codice ARC e non ARC. Tutto il codice compilato da ARC gestisce la sua memoria automaticamente all'utente. Dovresti abilitare ARC per il tuo progetto e quindi disabilitare ARC per i singoli file usando -fno-objc-arc o abilitare ARC per i file appena Swift usando -fobjc-arc (potrebbe non essere necessario in quanto il compilatore potrebbe aggiungerlo automaticamente). Il codice Swift viene infine compilato per utilizzare lo stesso runtime Objective C e le chiamate ARC inserite dal compilatore sono le stesse dell'obiettivo C. Dopo la compilazione, ARC e il codice non ARC si comportano allo stesso modo.

+0

Tutto ciò che scrivi è corretto ma non ha nulla a che fare con la domanda. Il problema non è "dopo" ma "durante la compilazione" in cui il compilatore legge i file di intestazione e il file di intestazione generato da Swift assume sempre ARC, quindi se si utilizza tale file di intestazione in classi non ARC, gli oggetti si comporteranno correttamente dopo compilazione, nessun problema, ma il compilatore genererà avvertimenti come per i file non ARC che importano questa intestazione, l'intestazione non è corretta e temo che sia così, non sono riuscito a trovare alcuna soluzione. – Mecki

+0

Cosa significa "non corretto"? Intendi modificatori voluti da ARC, come 'weak' e' strong'? –

+0

Se una proprietà non ha attributo di memoria, è 'assign' in non-ARC ma è' retain'/'strong' in ARC, quindi se si vuole usare lo stesso file header in entrambi, ARC e non-ARC Obj -C file, devi sempre usare un attributo di archiviazione esplicito, altrimenti il ​​compilatore penserà che questa è una proprietà 'assign' e una volta che questa è una proprietà' strong', ma in realtà, può essere solo uno, quindi uno l'assunzione sarà sempre falsa. Swift non imposta alcun attributo per i 'forti' vars, quindi Swift presuppone che il file di intestazione sia usato solo nel codice ARC. – Mecki

0

When I compile the project, I get warnings for every property emitted in the ProjectName-Swift.h bridge header

Sono riuscito a eliminare gli avvisi dopo aver convertito tutti i miei file in ARC. (Non si utilizza -fno-objc-arc)

0

Il file di intestazione generato da Swift per Obj-C sembra presupporre che ARC venga utilizzato nel codice Obj-C. A seconda della versione di Xcode e delle impostazioni di compilazione, è possibile che venga attivato un avviso che avverte l'utente quando una proprietà è implicitamente una proprietà assign, che è solo il caso in codice non ARC come nel codice ARC, le proprietà sono implicitamente strong (che è esattamente uguale a retain in codice non ARC). Con questo avviso abilitato, riceverai questo avviso ogni volta che importi l'intestazione generata in un file .m che non è ARC e Swift non ha impostato un attributo di memoria per quella proprietà.

Ma questo avviso non significa che il codice compilato non funzionerà correttamente in seguito. Nonostante il fatto che il compilatore ritiene che questa proprietà è solo assign, lo farà di sicuro non essere assign proprietà come Swift non possono nemmeno essere assign, possono essere strong o possono essere weak (weak non è lo stesso di assign! weak -properties diventano nil quando l'oggetto muore, assign - le proprietà diventano puntatori penzolanti e puntano ancora all'indirizzo in cui l'oggetto viveva). La cosa peggiore che ciò può causare, nonostante l'avviso, è un risultato errato dell'analizzatore di codice statico in quanto l'analizzatore potrebbe anche avvertire in che modo questa proprietà assign può infrangere il codice e ancora, l'analizzatore è errato in quanto la proprietà semplice non è assign in la realtà.

Per rimediare, l'unica cosa che è stato richiesto è quello di non fare affidamento su una proprietà di essere niente di default e sempre etichettare correttamente tutte le proprietà come strong, che funziona anche nel codice non-ARC (strong e retain sono solo sinonimi di il compilatore tratta entrambi esattamente la stessa cosa, quindi entrambi possono essere utilizzati in codice non ARC). La cosa divertente è abbastanza spesso che è esattamente ciò che Swift fa. Ho tonnellate di proprietà strong nella mia intestazione generata ma a quanto pare ci sono situazioni in cui Swift non lo farà (forse questo è in realtà un bug Swift).

E facile lavoro-a-rotonda per questo problema è quello di disabilitare solo l'avviso durante l'importazione l'intestazione generato, che può essere fatto come segue:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wobjc-property-no-attribute" 
#import "xxx-Swift.h" 
#pragma clang diagnostic pop 

proprio pack che in un altro file di intestazione, per esempio My-xxx-Swift.h e quindi importa solo My-xxx-Swift.h ovunque nel tuo codice.

Non lo disabiliterò per l'intero progetto (ad esempio nelle impostazioni di Xcode build) come di solito questo avvertimento è abbastanza significativo e può aiutare a prevenire bug terribili quando si mescola ARC e codice non ARC, come forse una proprietà non lo fa Si ha davvero l'attributo di archiviazione che si ritiene abbia e quindi quando si mixano ARC e non ARC, si consiglia vivamente di non fare mai affidamento su attributi impliciti e di rendere sempre lo storage esplicito.