'#selector', Objective-C'ye maruz kalmayan bir yöntemi ifade eder


105

AddTarget aracılığıyla parametreyi geçen yeni Xcode 7.3 genellikle benim için çalışıyor ancak bu durumda başlıktaki hatayı atıyor. Herhangi bir fikir? @Objc olarak değiştirmeye çalıştığımda bir tane daha atıyor

Teşekkür ederim!

cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

Aradığı seçici

func didTapCommentButton(post: Post) {
}

3
FeedViewController'ın sınıf bildirimi satırı neye benziyor? DidTapCommentButton nasıl ilan edilir? @Objc eklediğinizde hangi hatayı alıyorsunuz?
vacawama

1
Güncelle, yazımı düzenledim. Şu anda açık olduğu bilgisayardan uzaktayım, bu yüzden tam hata mesajını unutuyorum, ancak XCode'un bana eklememi söylediği ve ardından kendi kararıyla bir hata attığı durumlardan biriydi.
Echizzle

2
Sınıfınız beyan ediyor mu @objc, yoksa bir alt sınıfı NSObjectmı?
NRitH

2
Parantezleri kaldırmayı deneyebilir misin? Bir seçicide bir işlevi çağırmamanız gerektiği düşünüldüğünde alışılmadık bir durum.
DanielEdrisian

Yanıtlar:


173

Benim durumumda seçicinin işlevi şöyleydi private. Kaldırdığımda privatehata gitmişti. Aynısı için de geçerli fileprivate.

Swift 4'te fonksiyon bildirimine
eklemeniz gerekecek @objc. 4. süratliye kadar bu, dolaylı olarak çıkarılmıştır.


2
Ek olarak fileprivate.
hstdt

büyük yakalama @shaked
jbouaziz

@hstdt, yani ayarlarsanız fileprivateçözülür mü?
Hemang

2
@Hemang, hayır, @hstdt ne işe yaramayacağı ne privatede fileprivateişe yaramayacağı anlamına gelir
Gobe

Dinamik ile func yapmak, private / fileprivate kaldırmaktan daha uygundur.
Boon

57

@objcİle kullanmak için üzerinde didTapCommentButton(_:)niteliği kullanmanız gerekir #selector.

Bunu yaptığını söylüyorsun ama başka bir hata aldın. Tahminimce yeni hata PostObjective-C ile uyumlu bir tip değil. Bir yöntemi yalnızca tüm bağımsız değişken türleri ve dönüş türü Objective-C ile uyumluysa Objective-C'ye maruz bırakabilirsiniz.

PostBir alt sınıf oluşturarak bunu düzeltebilirsiniz NSObject, ama bu önemli olmayacak, çünkü argümanı zaten didTapCommentButton(_:)olmayacak Post. Bir eylem işlevinin argümanı eylemin göndericisidir ve bu gönderen commentButtonmuhtemelen a'dır UIButton. Şöyle beyan etmelisiniz didTapCommentButton:

@objc func didTapCommentButton(sender: UIButton) {
    // ...
}

Daha sonra Post, dokunulan düğmeye karşılık gelen sorunla karşılaşacaksınız . Bunu elde etmenin birden çok yolu var. Işte bir tane.

Anladığım kadarıyla (kodunuz söylediği için cell.commentButton) bir tablo görünümü (veya koleksiyon görünümü) oluşturuyorsunuz. Ve hücrenizin adlı standart olmayan bir özelliği commentButtonolduğundan, bunun özel bir UITableViewCellalt sınıf olduğunu varsayıyorum . Öyleyse hücrenizin böyle bir PostCellilan olduğunu varsayalım :

class PostCell: UITableViewCell {
    @IBOutlet var commentButton: UIButton?
    var post: Post?

    // other stuff...
}

Ardından, düğmeden görünüm hiyerarşisinde yukarı doğru yürüyebilir ve gönderiyi buradan PostCellalabilirsiniz:

@objc func didTapCommentButton(sender: UIButton) {
    var ancestor = sender.superview
    while ancestor != nil && !(ancestor! is PostCell) {
        ancestor = view.superview
    }
    guard let cell = ancestor as? PostCell,
        post = cell.post
        else { return }

    // Do something with post here
}

Global işlevle kullanmak istersem? @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
TomSawyer

Global bir işlevle kullanamazsınız.
soymak mayoff

8

Seçicinin bir sarmalayıcı işlevine işaret etmesini sağlamaya çalışın, bu da sizin temsilci işlevinizi çağırır. Bu benim için çalıştı.

cell.commentButton.addTarget(self, action: #selector(wrapperForDidTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

-

func wrapperForDidTapCommentButton(post: Post) {
     FeedViewController.didTapCommentButton(post)
}

1
Benim için çalıştı! bunun neden gerekli olduğundan hala emin değilim ama alacağım!
Paul Lehn

0

Bildiğiniz gibi selector[Hakkında] , Objective-Cçalışma zamanının kullanılması gerektiğini söylüyor . Varsayılan olarak Objective-C çalışma zamanı olarak işaretlenen privateveya fileprivategösterilmeyen bildirimler . Bu yüzden iki seçeneğiniz var:

  1. İzinizi privateveya fileprivatebeyanı ile @objc[Hakkında]
  2. Kullanım internal, public, openerişim değiştirici [Hakkında]
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.