Swift'in kendisi seçiciler kullanmaz - Objective-C'de seçicilerin kullandığı birkaç tasarım deseni Swift'te farklı çalışır. (Örneğin, protokol türleri veya is/ astestleri yerine isteğe bağlı zincirleme respondsToSelector:kullanın ve performSelector:daha iyi tür / bellek güvenliği yerine mümkün olan yerlerde kapatma kullanın .)
Ancak, zamanlayıcılar ve hedef / eylem modeli de dahil olmak üzere seçicileri kullanan bir dizi önemli ObjC tabanlı API vardır. Swift, Selectorbunlarla çalışmak için tür sağlar. (Swift bunu otomatik olarak ObjC SELtürü yerine kullanır .)
Swift 2.2 (Xcode 7.3) ve sonraki sürümlerde (Swift 3 / Xcode 8 ve Swift 4 / Xcode 9 dahil):
İfadeyi Selectorkullanarak Swift işlev türünden bir yapı oluşturabilirsiniz #selector.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
Bu yaklaşımla ilgili en güzel şey nedir? Bir işlev başvurusu Swift derleyici tarafından denetlenir, böylece #selectorifadeyi yalnızca gerçekten var olan ve seçici olarak kullanılmaya uygun olan sınıf / yöntem çiftleriyle kullanabilirsiniz (aşağıdaki "Seçici kullanılabilirliği" bölümüne bakın). Ayrıca, işlev türü adlandırma için Swift 2.2+ kurallarına göre işlev başvurunuzu yalnızca ihtiyacınız olduğu kadar özel yapmakta özgürsünüz .
(Bu aslında ObjC @selector()yönergesine göre bir gelişmedir , çünkü derleyicinin -Wundeclared-selectorkontrolü yalnızca adlandırılmış seçicinin var olduğunu doğrular. #selectorVarlığını, bir sınıfa üyeliği ve tür imzasını kontrol etmek için ilettiğiniz Swift işlev başvurusu .)
İfadeye ilettiğiniz işlev referansları için birkaç ek uyarı vardır #selector:
- Aynı taban adına sahip birden fazla işlev, işlev başvuruları için yukarıda belirtilen sözdizimi (örn.
insertSubview(_:at:)Vs insertSubview(_:aboveSubview:)) kullanılarak parametre etiketleriyle ayırt edilebilir . Ancak bir işlevin parametresi yoksa, onu tanımlamanın tek yolu as, işlevin tür imzası olan bir döküm kullanmaktır (örn. foo as () -> ()Vs foo(_:)).
- Swift 3.0 ve sonraki sürümlerde özellik alıcı / ayarlayıcı çiftleri için özel bir sözdizimi vardır. Örneğin a verildiğinde veya
var foo: Intkullanabilirsiniz .#selector(getter: MyClass.foo)#selector(setter: MyClass.foo)
Genel Notlar:
Kılıflar #selectorçalışma ve isimlendirme değildir: Bazen (dinamik objc zamanında kayıtlı yöntemlerle, örneğin) bir seçici yapmak için bir işlev başvurusu yok. Bu durumda, Selectorbir dizeden a oluşturabilirsiniz: örneğin Selector("dynamicMethod:")- derleyicinin geçerlilik denetimini kaybedersiniz. Bunu yaptığınızda, :her parametre için iki nokta üst üste ( ) dahil olmak üzere ObjC adlandırma kurallarına uymanız gerekir .
Seçici kullanılabilirliği: Seçici tarafından başvurulan yöntem ObjC çalışma zamanına maruz bırakılmalıdır. Swift 4'te, ObjC'ye maruz kalan her yöntemin bildirimi @objcöznitelikle önceden yapılmalıdır . (Önceki sürümlerde bu özelliği bazı durumlarda ücretsiz olarak edindiniz, ancak şimdi açıkça beyan etmeniz gerekiyor.)
privateSembollerin çalışma zamanına da maruz kalmadığını unutmayın - yönteminizin en azından internalgörünürlüğe sahip olması gerekir .
Anahtar yollar: Bunlar seçicilerle ilgilidir, ancak seçicilerle tamamen aynı değildir. Swift 3'te bunlar için de özel bir sözdizimi var: örn chris.valueForKeyPath(#keyPath(Person.friends.firstName)). Ayrıntılar için SE-0062'ye bakınız. KeyPathSwift 4'te daha da fazla şey , bu yüzden uygunsa seçiciler yerine doğru KeyPath tabanlı API'yi kullandığınızdan emin olun.
Swift'i Kakao ve Objective-C ile Kullanma bölümünde Objective-C API'leriyle Etkileşim altında seçiciler hakkında daha fazla bilgi edinebilirsiniz .
Not: Swift Selector2.2'den önce, uygun olduğundan StringLiteralConvertible, çıplak dizelerin seçici alan API'lara aktarıldığı eski kodu bulabilirsiniz. Bunları kullanmak için Xcode'da "Geçerli Swift Sözdizimine Dönüştür" komutunu çalıştırmak istersiniz #selector.
selector: test()testdönüş değerini çağırır veselectorargümana iletir.