"#selector" относится к методу, который не подвергается Objective-C

Новый Xcode 7.3, передающий параметр через addTarget, обычно работает для меня, но в этом случае он выдает ошибку в заголовке. Есть идеи? Он выбрасывает другой, когда я пытаюсь изменить его на @objc

Спасибо!

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

Селектор это звонит

func didTapCommentButton(post: Post) {
}

3 ответа

В моем случае функция селектора была private, Однажды я удалил private ошибка исчезла. То же самое касается fileprivate,

В Swift 4
Вам нужно будет добавить @objc к объявлению функции. До Swift 4 это было сделано неявно.

Вам нужно использовать @objc атрибут на didTapCommentButton(_:) использовать его с #selector,

Вы говорите, что сделали это, но у вас есть другая ошибка. Я думаю, что новая ошибка заключается в том, что Post не является типом, который совместим с Objective-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
}

Попробуйте использовать селектор, указывающий на функцию-оболочку, которая в свою очередь вызывает функцию-делегат. Это сработало для меня.

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

-

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

Как вы знаете selector [О] говорит, чтоObjective-Cследует использовать время выполнения. Объявления, отмеченные какprivate или fileprivateпо умолчанию не доступны для среды выполнения Objective-C. Поэтому у вас есть два варианта:

  1. Отметьте свой private или fileprivate заявление @objc [Около]
  2. Использовать internal, public, openмодификатор доступа [О программе]
Другие вопросы по тегам