'#selector'はObjective-Cに公開されていないメソッドを指します


105

addTargetを介してパラメーターを渡す新しいXcode 7.3は、通常は機能しますが、この場合、タイトルにエラーがスローされます。何か案は?@objcに変更しようとすると、もう1つスローされます

ありがとうございました!

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

それが呼び出しているセレクター

func didTapCommentButton(post: Post) {
}

3
FeedViewControllerのクラス宣言行はどのようになっていますか?didTapCommentButtonはどのように宣言されていますか?@objcを追加すると、どのようなエラーが発生しますか?
vacawama

1
更新、投稿を編集しました。すぐにオンになっているコンピューターから離れているので、正確なエラーメッセージを忘れてしまいましたが、XCodeがそれを追加するように指示し、独自の判断でエラーをスローする状況の1つでした。
Echizzle

2
あなたのクラスは宣言していますか@objc、それともそのサブクラスNSObjectですか?
NRitH 2016

2
かっこを削除してみてください。セレクターで関数を呼び出すべきではないことを考えると、異常です。
DanielEdrisian 2016

回答:


173

私の場合、セレクターの機能はでしたprivateprivateエラーを削除すると、エラーはなくなりました。同じことが当てはまりますfileprivate

Swift 4では、関数宣言
に追加する必要があり@objcます。Swift 4までは、これは暗黙的に推測されていました。


2
に加えてfileprivate
hstdt 2017年

グレートキャッチ@シェイク
jbouaziz

@hstdt、設定fileprivateすると、解決されますか?
Hemang

2
@Hemang、いいえ、@ hstdtはどちらprivateも機能しないことfileprivateを意味します
Gobe

funcをdynamicで作成することは、private / fileprivateを削除するよりも適切です。
ブーン2017

57

で使用するには、@objc属性on didTapCommentButton(_:)を使用する必要があります#selector

あなたはそれをしたと言いますが、あなたは別のエラーを得ました。私の推測では、新しいエラーはPostObjective-Cと互換性のあるタイプではないということです。メソッドのすべての引数の型と戻り値の型がObjective-Cと互換性がある場合にのみ、Objective-Cにメソッドを公開できます。

Postサブクラスを作成することで修正できますが、NSObjectへの引数didTapCommentButton(_:)Postとにかくないので、それは問題にはなりません。アクション関数への引数はアクションの送信者であり、その送信者はでありcommentButton、おそらくUIButtonです。次のdidTapCommentButtonように宣言する必要があります。

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

その後、取得の問題に直面します Post、タップされたボタンに対応するものをします。それを取得する方法はいくつかあります。ここにある。

cell.commentButtonテーブルビュー(またはコレクションビュー)を設定していることを(コードでと言っているので)収集します。また、セルにはという非標準のプロパティcommentButtonがあるため、カスタムUITableViewCellサブクラスであると想定します。だからあなたの細胞が次のPostCellように宣言されていると仮定しましょう:

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

    // other stuff...
}

次に、ボタンからビュー階層を上に移動してを見つけ、PostCellそこから投稿を取得できます。

@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
}

グローバル機能で使用したい場合は?@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
TomSawyer

グローバル関数では使用できません。
rob mayoff 2016年

8

セレクターがラッパー関数を指すようにして、ラッパー関数がデリゲート関数を呼び出すようにします。それでうまくいきました。

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

-

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

1
私のために働いた!なぜこれが必要なのかまだわかりませんが、私はそれを取ります!
Paul Lehn 2016年

0

ご存じのとおり、selector[About]Objective-Cランタイムを使用する必要があると述べています。マークが付けられている宣言、privateまたはデフォルトでfileprivate Objective-Cランタイムに公開されていない宣言。これが、2つのバリアントがある理由です。

  1. [概要]でprivateまたはfileprivate宣言をマークしてください@objc
  2. 使用internalpublicopenアクセス修飾子[概要]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.