Dinamik yöntem çağrısı, yöntemleri çalışma zamanında (runtime) ismi ile çağırma yeteneğidir, derleme zamanında değil. Swift'te bu, @objc ve dynamic modifikatörleri sayesinde Objective-C runtime ile etkileşim yoluyla mümkündür veya AnyObject protokolü kullanılarak yapılabilir.
Mekanizmalar:
@objc — bir yöntemi/özelliği/sınıfı Objective-C runtime'a dışa aktarmak için işaretler.dynamic — çağrının statik çağrı (vtable tablosu) yerine Objective-C mesaj gönderimi ile gerçekleştirilmesini gerektirir.Kısıtlamalar:
@objc olarak işaretlenmiş protokollerle çalışır.@objc niteliğine sahip veya NSObject'tan türemiş olarak işaretlenmiş yöntem/özelliklerle ilgilidir.Örnek:
import Foundation class Person: NSObject { @objc dynamic func sayHello() -> String { return "Merhaba!" } } let person = Person() // Selector (perform:) aracılığıyla dinamik çağrı: if person.responds(to: #selector(Person.sayHello)) { if let result = person.perform(#selector(Person.sayHello))?.takeUnretainedValue() as? String { print(result) // "Merhaba!" } } }
Aynı şekilde, AnyObject aracılığıyla optional chaining ile işlevler çağrılabilir:
@objc protocol Greeter { @objc optional func greet() } class Robot: NSObject, Greeter { func greet() { print("Beep-beep!") } } let anyGreeter: AnyObject = Robot() anyGreeter.greet?() // "Beep-beep!"
struct dinamik yöntem çağrısını @objc, dynamic veya AnyObject ile destekleyebilir mi?
Cevap: Hayır, yalnızca NSObject'tan türemiş sınıflar veya @objc modifikatörüne sahip olan sınıflar/protokoller bu tür mekanizmaları destekleyebilir. Struct ve enum'lar Objective-C runtime ile uyumlu değildir, bu nedenle dinamik katılımcılar olamazlar.
Hikaye
Projede delegasyon için @objc protokolü kullanılıyordu. Geliştiricilerden biri delegasyon sınıfının NSObject'tan türemesini kaldırdı, bu nedenle optional yöntemler optional chaining ile çağrılamaz hale geldi. Mimari çalışmamaya başladı, testler sürekli başarısız oldu.
Hikaye
Geliştirici dinamik olarak işaret edildiği için bir yapının özelliği üzerinde KVO (key-value observing) kullanmaya çalıştı. Kod derlendi ama beklendiği gibi çalışmadı, çünkü struct Objective-C runtime'ı desteklemiyor. Değişikliklere dinamik tepki vermedi, bu da UI güncellemelerinin atlanmasına neden oldu.
Hikaye
Sınıf genişletmesinde, perform(_: aracılığıyla çağrılan işlevin @objc modifikatörünü eklemeyi unuttular. Sonuç olarak, ilişkili bir seçici çağrıldığında üretimde çökme yaşandı. Sebebi uzun süre arandı, ta ki işlevin Objective-C'ye dışa aktarılmadığı fark edilene kadar.