2014-11-03 19 views
8

Ich möchte erkennen, ob der Benutzer Transparenz reduzieren aktiviert hat. Es ist einfach, Sie rufen einfach die Funktion UIAccessibilityIsReduceMotionEnabled() und es gibt eine Bool zurück. Aber meine App zielt auf iOS 7 und 8, und diese Funktion ist nicht auf iOS 7.Überprüfen Sie, ob eine Funktion in Swift verfügbar ist.

In Objective-C, das ist, wie ich überprüft, ob diese Funktion vorhanden ist:

if (UIAccessibilityIsReduceMotionEnabled != NULL) { } 

In Swift Ich kann nicht herausfinden, wie man überprüft, ob es existiert oder nicht. Nach this answer können Sie einfach optionale Verkettung verwenden, und wenn es nil ist, dann existiert es nicht, aber das ist offensichtlich auf Obj-C-Protokolle beschränkt. Xcode 6.1 mag das nicht:

let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled?() 

Es möchte, dass Sie die? Entfernen. Und natürlich stürzt es bei iOS 7 ab, weil diese Funktion nicht existiert.

Was ist der richtige Weg zu prüfen, ob diese Arten von Funktionen existieren?

+0

Klammern nach einem Funktionsausdruck Aufrufen der Funktion. Was passiert, wenn du sie auslässt? – outis

+0

Wenn du ausgibst() sagt es dasselbe - lösche das?: 'Operand von postfix '?' sollte optionalen Typ haben; Typ ist '() -> Bool''. Auch wenn du das verschiebst? Nach der(), ist es die gleiche Fehlermeldung. – Joey

+0

Ich vermute, dass es tatsächlich noch nicht verfügbar ist. Aus meiner Sicht wird die optionale Verkettung für Klassenvariablen verwendet. 'UIAccessibilityIsReduceMotionEnabled' ist mehr wie statische Funktion – Peter

Antwort

7

Eine korrekte Verfügbarkeitsprüfung wurde in Swift 2 hinzugefügt. Dies wird gegenüber anderen hier genannten Optionen empfohlen.

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

Sie könnten überprüfen, um zu sehen, ob Sie in iOS 8 oder höher laufen -

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

ich glaube nicht gibt es eine andere Art und Weise zu erzählen. Also, in der Theorie, wenn Sie in der Lage, zu überprüfen, würde versuchen, auf den Funktionsnamen ohne die () zugreifen würde geben Sie nil in iOS 7 und die () -> Bool Funktion in iOS 8. Allerdings, damit dies geschehen, müsste UIAccessibilityIsReduceMotionEnabled definiert werden als (() -> Bool)?, was es nicht ist. Testen Sie es aus einer Funktionsinstanz in beiden Versionen von iOS ergibt, dass, wenn in iOS 7 genannt stürzt:

Die einzige Art, wie ich es ohne Prüfung die Version zu tun, sehen kann, ist einfach Ihre eigene C-Funktion zu definieren, um zu überprüfen in Ihrer Überbrückung Header-Datei, und nennen das:

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

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

Ja, das ist ein Weg, es zu tun. Apple würde dagegen aber empfehlen und hat in der Vergangenheit während der WWDC Sitzungen. Sie müssen häufig feststellen, ob eine Funktion vorhanden ist, insbesondere wenn mehrere Betriebssysteme unterstützt werden. Ist das etwas, das in Swift nicht existiert? Das klingt verrückt. – Joey

+0

Verrückt in der Tat. Siehe Aktualisierung. –

+1

Danke, Güte, das ist schrecklich. : P Zeit zum Einreichen einer Erweiterungsanforderung! Ich werde Obj-C nicht verwenden, diese App ist pure Swift. – Joey

5

wenn Sie ein wenig mit dem sein frech in Ordnung sind, können Sie immer die UIKit binäre öffnen Sie die Bibliothek Loader und sehen, ob es das Symbol auflösen kann:

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!") 
} 

Die dlopen und dlsym Anrufe können irgendwie teuer sein, also würde ich empfehlen, den Griff dlopen für das Leben der Anwendung offen zu halten und irgendwo das Ergebnis des Versuchens zu dlsym zu speichern. Wenn Sie nicht, stellen Sie sicher, dass Sie dlclose es.

Soweit ich weiß, ist dies AppStore sicher, da UIAccessibilityIsReduceMotionEnabled eine öffentliche API ist.

+0

nett ein @aethe – NSTJ

0

Von dem Apple Developer docs (Using Swift with Cocoa and Objective-C (Swift 3) > Interoperability > Adopting Cocoa Design Patterns > API Availability):

Swift Code, um die Verfügbarkeit von APIs als Bedingung bei Laufzeit nutzen kann.Verfügbarkeitsprüfungen können anstelle einer Bedingung in einer Steuerflussanweisung verwendet werden, wie z. B. einer , oder while Anweisung.

das vorherige Beispiel nehmen, können Sie die Verfügbarkeit in einer if Anweisung überprüfen requestWhenInUseAuthorization() nur zu nennen, wenn die Methode zur Laufzeit verfügbar ist:

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

Alternativ können Sie die Verfügbarkeit in einer guard Anweisung überprüfen , , die außerhalb des Gültigkeitsbereichs endet, es sei denn, das aktuelle Ziel erfüllt die Anforderungen . Dieser Ansatz vereinfacht die Logik der Handhabung von unterschiedlichen Plattformfähigkeiten.

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

Jede Plattform Argument besteht aus einer der Plattformnamen unten aufgeführt, gefolgt von Versionsnummer entspricht. Das letzte Argument ist ein Sternchen (*), mit dem potenzielle zukünftige Plattformen behandelt werden.

Platform Namen:

  • iOS
  • iOSApplicationExtension
  • macOS
  • macOSApplicationExtension
  • watchOS
  • watchOSApplicationExtension
  • tvOS
  • tvOSApplicationExtension
Verwandte Themen