2015-12-01 10 views
12

Swift 2 ha API availability checking.Perché ogg-c non ha il controllo della disponibilità dell'API?

Il compilatore vi darà un errore quando si utilizza un API troppo nuova per la vostra obiettivo minimo OS

Perché l'obiettivo-c compilatore non può fare l'equivalente?

I googled obiettivo c Verifica disponibilità API e solo i risultati rapidi 2 sono usciti, quindi presumo che il compilatore per l'obiettivo c non possa farlo.

+0

Swift è stato progettato con questa funzione in mente, quindi Apple potrebbe aggiungere la funzionalità senza creare incompatibilità o ostacolare le normali capacità del linguaggio. Objective-C è molto dinamico, ed è difficile dire in fase di compilazione ciò che sarà o non sarà disponibile in fase di runtime. – Avi

+0

Date un'occhiata a https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html potete essenzialmente ottenere la stessa cosa da giocherellando con lo SDK di base e le destinazioni di distribuzione ma è più ingombrante. – pvg

+1

puoi usare 'respondsToSelector: @selector (methodName)' per verificarne la disponibilità, in quanto non esiste un altro meccanismo dedicato come swift. –

risposta

19

L'avviso (Swift lo rende un errore) non è stato implementato nel compilatore Clang per anni, ma non è una limitazione Objective-C intrinseca (anche se a causa della sua natura dinamica, non sarà possibile cattura tutti i casi), né la terminologia Swift.

Le macro di Apple (per esempio, NS_CLASS_AVAILABLE) e gli attributi sorgente (__attribute__((visibility(...))), __attribute__((availability(...)))) per annotare intestazioni con informazioni sulla disponibilità sono stati lì per anni, e sono ampiamente utilizzati in SDK di Apple. Le macro sono definite negli NSObjCRuntime.h, e negli header di sistema Availability.h/AvailabilityMacros.h e il compilatore può (e lo fa) leggerli.

Nei primi mesi del 2015, il -Wpartial-availability avvertimento has been added-master ramo di Clang, ma questo commit/avviso non aveva fatto la sua strada in versione di Apple di Clang fino (compreso) Xcode 7.2. Otterrai un log unknown warning option quando aggiungi il flag di avviso a un progetto in Xcode 7.2, ma il flag è disponibile in Xcode 7.3. Al momento non è disponibile alcuna impostazione predefinita, ma puoi aggiungere il flag a Other Warning Flags in Impostazioni di creazione.

Esistono altri strumenti che utilizzano librerie LLVM per rilevare API parzialmente disponibili, ad esempio Deploymate. Per la mia tesi di diploma, ho sviluppato uno strumento che si integra direttamente in Xcode e si basa su una modifica al compilatore Clang. Il codice è ancora online, ma non ho seguito lo sviluppo generale di Clang, quindi non sarà di grande utilità, tranne che per scopi di apprendimento. Tuttavia, il codice "ufficiale" (linkato sopra) è molto più pulito e migliore.

Modifica: A partire da Xcode 9, il controllo di disponibilità funzionerà anche per Objective-C (e C). Invece di utilizzare il flag di avvertimento sopra menzionato, che non supporta l'aumento temporaneo/locale della distribuzione e causa quindi molti falsi positivi, c'è -Wunguarded-availability e if (@available(iOS 11, *)) {...} per controllare e aumentare la destinazione di distribuzione per il seguente blocco di codice. È disattivato per impostazione predefinita, ma lo standard -Wunguarded-availability-new sarà attivato per impostazione predefinita e inizierà a controllare qualsiasi elemento che vada oltre iOS/tvOS 11, watchOS 4 e High Sierra. Maggiori dettagli su questo possono essere trovati nel Xcode 9 beta release notes, che attualmente richiede l'accesso con un account sviluppatore.

+0

Grazie per aver collegato deploymate e la tua tesi. Sembra interessante – okysabeni

+0

@hagi. Grazie per il punto sul flag di disponibilità parziale. Sono stato in grado di collegare l'ultimo clang con Xcode 7.2 e ottenere gli avvertimenti. https://gist.github.com/vigneshr89/befe6a99e7979772e449 – Vignesh

+1

I beta beta di Xcode 7.3 sembrano venire con una versione di Clang che supporta la bandiera fuori dalla scatola :) – hagi

-3

Ovviamente, si otterranno errori nel codice Objective-C. Ma non troverai risultati in google per Objective-C, se usi un termine definito per Swift poiché non troverai il sito kisuaheli in google se cerchi una parola tedesca. ;-)

Si otterrà un errore che collega il codice Objective-C a un SDK troppo vecchio. Questo è semplicemente perché il metodo utilizzato o la classe o $ qualsiasi cosa non è definita nell'intestazione per quell'SDK. Di nuovo, ovviamente.

Questo è tipico marketing Swift di Apple: a causa dell'incapacità di Swift devono estendere la lingua per ottenere qualcosa, cosa abbastanza semplice in Objective-C. Invece di chiarire che questo è il risultato della povertà di Swift, ti dicono che questa è una grande caratteristica di Swift. È come tagliarsi le dita e poi dire: "Abbiamo la grande caratteristica di gesso !!!!!!!!" E devi aspettare solo alcuni giorni e uno si avvicina a SO con la Q: "Perché Objective-C non ha la caratteristica dell'intonaco? ??????" La semplice risposta: non ti taglia le dita.

Il problema è non per generare gli errori. Il problema è avere un codice sorgente per tutte le versioni, quindi puoi semplicemente cambiare la versione dell'SDK e ottenere un nuovo codice (o errori). Ne hai bisogno per una manutenzione più semplice.

in Objective-C si può semplicemente utilizzare la risposta trovata qui: Conditionally Hide Code from the Compiler o si può fare che in fase di esecuzione come detto nei commenti al D. (Ma questa è una soluzione diversa del problema per natura, perché un approccio dinamico invece di uno statico come devi fare in Swift.)

Il motivo per cui una caratteristica della lingua in Swift è che Swift non ha alcun preprocessore, quindi la soluzione Objective-C non funzionerebbe in Swift. Pertanto, il codice condizionale sarebbe impossibile in Swift e hanno dovuto aggiungere l'intonaco, eh, funzione della lingua.

3

L'obiettivo C non ha disponibilità controllo come parte della lingua, poiché lo stesso risultato è disponibile tramite il preprocessore Objective C. Questo è il modo "tradizionale" di farlo in linguaggi derivati ​​da C.

Vuoi sapere se è compilato in modalità di debug?

#ifdef DEBUG 
    // code which will be inserted only if compiled in debug mode 
#endif 

Vuoi controllare in fase di compilazione per una versione minima? Utilizzare l'intestazione Availability.h in iOS e intestazioni simili per Mac OS X.

Questo file si trova nella directory/usr/include.

solo testare __IPHONE_OS_VERSION_MAX_ALLOWED con il preprocessore, per es .:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 
      if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { 
       [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil]]; 
      }else{ 
       [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)]; 
      } 
#else 
      [[UIApplication sharedApplication] registerUserNotificationSettings: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)]; 
#endif 

Come Swift non ha un preprocessore, hanno dovuto inventare un modo di fare questo tipo di controlli all'interno del linguaggio stesso.

Se si desidera controllare la disponibilità di un metodo in fase di esecuzione, si prega di notare che il modo appropriato è quello di utilizzare il metodo di respondsToSelector :, o instancesRespondToSelector: (quest'ultima a livello di classe).

Generalmente si desidera combinare entrambi gli approcci, compilare la compilazione condizionale e il controllo runtime.

Verifica presenza presenza metodo C, ad es. a livello di classe:

if ([UIImagePickerController instancesRespondToSelector: 
       @selector (availableCaptureModesForCameraDevice:)]) { 
    // Method is available for use. 
    // Your code can check if video capture is available and, 
    // if it is, offer that option. 
} else { 
    // Method is not available. 
    // Alternate code to use only still image capture. 
} 

Se si desidera verificare se una funzione C esiste in fase di esecuzione, è ancora più semplice: se esiste, la funzione stessa non è nullo.

Non è possibile utilizzare lo stesso approccio identico in entrambe le lingue.

37

Xcode 9.0 porta la disponibilità runtime il controllo della sintassi da Swift a Objective-C:

if (@available(macOS 10.9, *)) 
{ 
// call 10.9+ API 
} 
else 
{ 
// fallback code 
} 

questo viene fornito completo di avvertenze per chiamare le API più recenti rispetto a vostra destinazione di distribuzione (se tali chiamate non sono avvolti in assegni).

finalmente;)

+0

È un controllo di runtime? – Itachi

+0

sì il suo controllo di runtime – user1259710

Problemi correlati