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
/ as
testleri 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, Selector
bunlarla çalışmak için tür sağlar. (Swift bunu otomatik olarak ObjC SEL
tü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 Selector
kullanarak 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 #selector
ifadeyi 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-selector
kontrolü yalnızca adlandırılmış seçicinin var olduğunu doğrular. #selector
Varlığı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: Int
kullanabilirsiniz .#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, Selector
bir 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.)
private
Sembollerin çalışma zamanına da maruz kalmadığını unutmayın - yönteminizin en azından internal
gö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. KeyPath
Swift 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 Selector
2.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()
test
dönüş değerini çağırır veselector
argümana iletir.