Zayıf Bağlama - bir sınıfın var olup olmadığını kontrol edin ve bu sınıfı kullanın


87

Evrensel bir iPhone uygulaması oluşturmaya çalışıyorum, ancak yalnızca SDK'nın daha yeni bir sürümünde tanımlanan bir sınıfı kullanıyor. Çerçeve daha eski sistemlerde bulunur, ancak çerçevede tanımlanan bir sınıf yoktur.

Bir çeşit zayıf bağlantı kullanmak istediğimi biliyorum, ancak çalışma zamanı kontrolleriyle ilgili konuşmalar bulabildiğim herhangi bir dokümantasyon işlevin var olup olmadığını nasıl kontrol edebilirim?


Sınıf nedir? Belki başka geçici çözümler vardır.
Marcelo Cantos

Yanıtlar:


164

TLDR

Akım:

  • Swift :if #available(iOS 9, *)
  • Obj-C, iOS :if (@available(iOS 11.0, *))
  • Obj-C, OS X :if (NSClassFromString(@"UIAlertController"))

Eski:

  • Swift (2.0'dan önceki sürümler) :if objc_getClass("UIAlertController")
  • Obj-C, iOS (4.2'den önceki sürümler) :if (NSClassFromString(@"UIAlertController"))
  • Obj-C, iOS (11.0'dan önceki sürümler) :if ([UIAlertController class])

Swift 2+

Geçmişte belirli işletim sistemi sürümleri yerine yetenekleri (veya sınıf varlığını) kontrol etmeniz önerilmiş olsa da, kullanılabilirlik kontrolünün getirilmesi nedeniyle Swift 2.0'da bu pek işe yaramıyor .

Bunun yerine şu yolu kullanın:

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(...)
}

Not: Bunun yerine kullanmayı denerseniz objc_getClass(), aşağıdaki hatayı alırsınız:

⛔️ 'UIAlertController' yalnızca iOS 8.0 veya daha yeni sürümlerde kullanılabilir.


Swift'in önceki sürümleri

if objc_getClass("UIAlertController") != nil {
    let alert = UIAlertController(...)
} else {
    let alert = UIAlertView(...)
}

Veya seçeneğinden objc_getClass() daha güvenilir olduğunuNSClassFromString()objc_lookUpClass() unutmayın .


Objective-C, iOS 4.2+

if ([SomeClass class]) {
    // class exists
    SomeClass *instance = [[SomeClass alloc] init];
} else {
    // class doesn't exist
}

Daha fazla ayrıntı için kod 007'nin cevabına bakın .


OS X veya iOS'un önceki sürümleri

Class klass = NSClassFromString(@"SomeClass");
if (klass) {
    // class exists
    id instance = [[klass alloc] init];
} else {
    // class doesn't exist
}

Kullanın NSClassFromString(). Dönerse nil, sınıf mevcut değildir, aksi takdirde kullanılabilecek sınıf nesnesini döndürür.

Bu belgede Apple'a göre önerilen yoldur :

[...] Kodunuz, kullanarak [a] sınıfının varlığını test eder ve bu, [] sınıfı NSClassFromString()varsa geçerli bir sınıf nesnesi döndürür, yoksa sıfırdır. Sınıf mevcutsa, kodunuz onu kullanabilir [...]


Teşekkürler. Diğerleri için yanıtı tamamlamak için, bir kez Classtarafından döndürülen örneği kullanarak oluşturduğunuz sınıfı NSClassFromString(atayın id) ve bu örnekteki seçicileri çağırın.
psychotik

2
Özellikle, OSX'teki tek yol budur, ancak iOS (4.2+) için "en iyi" yol değildir, ancak işe yarayacaktır. Code007'nin özellikle iOS için yanıtına bakın.
Ben Mosher

Ya sınıfım gerçek bir sınıf değil de bir C yapısı ise?
Nathan H

Swift 4.1 yeni çekle geliyor canImport. Teklif
dispatchMain

69

İOS 4.2 veya sonraki bir temel SDK kullanan yeni projeler için, çalışma zamanında zayıf bağlantılı sınıfların kullanılabilirliğini kontrol etmek için NSObject sınıf yöntemini kullanmak olan bu yeni önerilen yaklaşım vardır. yani

if ([UIPrintInteractionController class]) {
    // Create an instance of the class and use it.
} else {
    // Alternate code path to follow when the
    // class is not available.
}

kaynak: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-SW3

Bu mekanizma, iOS'taki çoğu çerçeve için mevcut olan NS_CLASS_AVAILABLE makrosunu kullanır (henüz NS_CLASS_AVAILABLE'ı desteklemeyen bazı çerçeveler olabilir - bunun için iOS sürüm notuna bakın). Apple'ın yukarıda verilen dokümantasyon bağlantısında okunabilecek ekstra ayar yapılandırması da gerekebilir, ancak bu yöntemin avantajı statik tip denetimi almanızdır.


3
Geç oyuna Biraz ama içerdiği inşa kod çalışırken ben sadece bu konuda karşılaştım UIAlertControllerhala 7. code007 cevabı doğrudur iOS desteklerken, ancak gerektiğinde ekstra konfigürasyon zayıf bağlantı (den kümesidir Requirediçin Optionalprojenizde) UIKit (en azından bu durum için).
Evan R
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.