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

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

Спасибо!

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

Селектор, вызывающий

func didTapCommentButton(post: Post) {
}

Ответ 1

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

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

Ответ 2

Вам нужно использовать атрибут @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
}

Ответ 3

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

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

-

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