Próbuję stworzyć uniwersalną aplikację na iPhone'a, ale używa ona klasy zdefiniowanej tylko w nowszej wersji SDK. Framework istnieje w starszych systemach, ale klasa zdefiniowana w frameworku nie.
Wiem, że chcę użyć jakiegoś słabego linkowania, ale każda dokumentacja, którą mogę znaleźć, mówi o sprawdzaniu istnienia funkcji w czasie wykonywania - jak sprawdzić, czy klasa istnieje?
ios
backwards-compatibility
weak-linking
psychotik
źródło
źródło
Odpowiedzi:
TLDR
Obecny:
if #available(iOS 9, *)
if (@available(iOS 11.0, *))
if (NSClassFromString(@"UIAlertController"))
Dziedzictwo:
if objc_getClass("UIAlertController")
if (NSClassFromString(@"UIAlertController"))
if ([UIAlertController class])
Swift 2+
Chociaż historycznie zaleca się sprawdzanie możliwości (lub istnienia klas), a nie konkretnych wersji systemu operacyjnego, nie działa to dobrze w Swift 2.0 ze względu na wprowadzenie sprawdzania dostępności .
Zamiast tego użyj tego sposobu:
if #available(iOS 9, *) { // You can use UIStackView here with no errors let stackView = UIStackView(...) } else { // Attempting to use UIStackView here will cause a compiler error let tableView = UITableView(...) }
Uwaga: jeśli zamiast tego spróbujesz użyć
objc_getClass()
, pojawi się następujący błąd:Poprzednie wersje Swift
if objc_getClass("UIAlertController") != nil { let alert = UIAlertController(...) } else { let alert = UIAlertView(...) }
Zauważ, że
objc_getClass()
jest bardziej niezawodny niżNSClassFromString()
lubobjc_lookUpClass()
.Objective-C, iOS 4.2+
if ([SomeClass class]) { // class exists SomeClass *instance = [[SomeClass alloc] init]; } else { // class doesn't exist }
Zobacz odpowiedź code007, aby uzyskać więcej informacji .
OS X lub poprzednie wersje iOS
Class klass = NSClassFromString(@"SomeClass"); if (klass) { // class exists id instance = [[klass alloc] init]; } else { // class doesn't exist }
Użyj
NSClassFromString()
. Jeśli zwrócinil
, klasa nie istnieje, w przeciwnym razie zwróci obiekt klasy, którego można użyć.Jest to zalecany sposób według Apple w tym dokumencie :
źródło
Class
instancji zwróconej przezNSClassFromString
(przypisz ją doid
) i wywołaj selektory tej instancji.canImport
. WniosekW przypadku nowych projektów korzystających z podstawowego zestawu SDK systemu iOS 4.2 lub nowszego istnieje nowe zalecane podejście polegające na użyciu metody klasy NSObject w celu sprawdzenia dostępności słabo połączonych klas w czasie wykonywania. to znaczy
if ([UIPrintInteractionController class]) { // Create an instance of the class and use it. } else { // Alternate code path to follow when the // class is not available. }
źródło: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-SW3
Ten mechanizm wykorzystuje makro NS_CLASS_AVAILABLE, które jest dostępne dla większości frameworków w iOS (zauważ, że mogą istnieć frameworki, które jeszcze nie obsługują NS_CLASS_AVAILABLE - sprawdź informacje o wydaniu iOS). Może być również wymagana dodatkowa konfiguracja ustawień, którą można przeczytać w podanym powyżej łączu do dokumentacji firmy Apple, jednak zaletą tej metody jest to, że uzyskuje się statyczne sprawdzanie typu.
źródło
UIAlertController
, mimo że nadal obsługuje iOS 7. Odpowiedź code007 jest poprawna, ale potrzebna dodatkowa konfiguracja to słabe połączenie (ustawienie zRequired
doOptional
) UIKit w twoim projekcie (przynajmniej w tej sytuacji).