2014-11-03 16 views
8

Vorrei rilevare se l'utente ha attivato Riduci trasparenza. È semplice chiamare la funzione UIAccessibilityIsReduceMotionEnabled() e restituisce un Bool. Ma si rivolge la mia app iOS 7 e 8 e questa funzione non è disponibile su iOS 7.Controllare se una funzione è disponibile in Swift?

in Objective-C, questo è come ho controllato per vedere se quella funzione esiste:

if (UIAccessibilityIsReduceMotionEnabled != NULL) { } 

In Swift , Non riesco a capire come verificare se esiste o no. Secondo this answer, puoi semplicemente usare il concatenamento opzionale e se è nil allora non esiste, ma a quanto pare è limitato ai protocolli Obj-C. Xcode 6.1 non piace questo:

let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled?() 

Vuole che tu rimuova il?. E ovviamente se lo fai, si bloccherà su iOS 7 perché quella funzione non esiste.

Qual è il modo corretto per verificare se questi tipi di funzioni esistono?

+0

parentesi dopo un'espressione di funzione invocano la funzione. Cosa succede se li lasci fuori? – outis

+0

Se si interrompe(), si dice la stessa cosa: cancellare il?: 'Operando di postfix '?' dovrebbe avere tipo opzionale; il tipo è '() -> Bool''. Inoltre se muovi il? dopo(), è tutto lo stesso messaggio di errore. – Joey

+0

Sospetto che non sia effettivamente ancora disponibile. Dalla mia comprensione, il concatenamento opzionale viene utilizzato per le variabili di classe. 'UIAccessibilityIsReduceMotionEnabled' è più simile alla funzione statica – Peter

risposta

7

Un controllo corretto per la disponibilità è stato aggiunto in Swift 2. Si consiglia su altre opzioni menzionate qui.

var shouldApplyMotionEffects = true 
if #available(iOS 8.0, *) { 
    shouldApplyMotionEffects = !UIAccessibilityIsReduceMotionEnabled() 
} 
2

Si potrebbe verificare per vedere se si sta eseguendo in iOS 8 o superiore -

var reduceMotionEnabled = false 
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) { 
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled() 
} 

io non credo che c'è un altro modo per dire. Quindi, in teoria, se sei stato in grado di verificare, provare ad accedere al nome della funzione senza lo () ti darebbe nil in iOS 7 e la funzione () -> Bool in iOS 8. Tuttavia, affinché ciò avvenga, è necessario definire UIAccessibilityIsReduceMotionEnabled come (() -> Bool)?, che non è. Testing fuori rendimenti un'istanza funzione in entrambe le versioni di iOS che si blocca se chiamati in iOS 7:

L'unico modo che posso vedere di farlo senza testare la versione è semplicemente quello di definire una funzione C per controllare nel file di intestazione colmare, e chiamare che:

// ObjC 
static inline BOOL reduceMotionDetectionIsAvailable() { 
    return (UIAccessibilityIsReduceMotionEnabled != NULL); 
} 

// Swift 
var reduceMotionEnabled = false 
if reduceMotionDetectionIsAvailable() { 
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled() 
} 
+0

Sì, questo è un modo per farlo. Apple lo consiglierebbe contro e lo ha fatto in passato durante le sessioni del WWDC. Molte volte è necessario rilevare se esiste una funzione, specialmente quando si supportano più SO. È qualcosa che non esiste in Swift? Sembra pazzesco. – Joey

+0

Pazzesco davvero. Vedi l'aggiornamento. –

+1

Grazie, Dio è terribile. : P Tempo di presentare una richiesta di miglioramento! Non userò Obj-C, questa app è pura Swift. – Joey

5

Se stai bene con l'essere un po 'sfacciato, si può sempre aprire il binario UIKit usando il caricatore biblioteca e vedere se è in grado di risolvere il simbolo:

let uikitbundle = NSBundle(forClass: UIView.self) 
let uikit = dlopen(uikitbundle.executablePath!, RTLD_LAZY) 
let handle = dlsym(uikit, "UIAccessibilityIsReduceMotionEnabled") 
if handle == nil { 
    println("Not available!") 
} else { 
    println("Available!") 
} 

Le chiamate dlopen e dlsym possono essere abbastanza costose, quindi consiglierei di mantenere l'handle dlopen aperto per la durata dell'applicazione e di memorizzare da qualche parte il risultato di provare su dlsym. Se non lo fai, assicurati di averlo dlclose.

Per quanto ne so questo è sicuro da AppStore, dal momento che UIAccessibilityIsReduceMotionEnabled è un'API pubblica.

+0

nice one @aethe – NSTJ

0

Dalla documentazione di Apple Developer (Using Swift with Cocoa and Objective-C (Swift 3) > Interoperability > Adopting Cocoa Design Patterns > API Availability):

codice Swift può utilizzare la disponibilità di API come una condizione a run-time.I controlli di disponibilità possono essere utilizzati al posto di una condizione in un prospetto del flusso di controllo , ad esempio if, guard o .

Prendendo l'esempio precedente, è possibile verificare la disponibilità in un comunicato if chiamare requestWhenInUseAuthorization() solo se il metodo è disponibile in fase di esecuzione:

let locationManager = CLLocationManager() 
if #available(iOS 8.0, macOS 10.10, *) { 
    locationManager.requestWhenInUseAuthorization() 
} 

In alternativa, è possibile verificare la disponibilità in un comunicato guard , che esce dall'ambito di applicazione a meno che la destinazione corrente soddisfi i requisiti specificati da . Questo approccio semplifica la logica di gestione delle funzionalità della piattaforma diverse.

let locationManager = CLLocationManager() 
guard #available(iOS 8.0, macOS 10.10, *) else { return } 
locationManager.requestWhenInUseAuthorization() 

Ogni argomento piattaforma è costituita da una delle piattaforme elencate di seguito, seguito dal corrispondente numero di versione. L'ultimo argomento è un asterisco (*), che viene utilizzato per gestire potenziali piattaforme future.

Nomi delle piattaforme:

  • iOS
  • iOSApplicationExtension
  • macOS
  • macOSApplicationExtension
  • watchOS
  • watchOSApplicationExtension
  • tvOS
  • tvOSApplicationExtension
Problemi correlati