"classname не имеет имени участника" при добавлении цели UIButton
Super newb в разработке Swift и iOS.
Я следую этот учебник о внедрении настраиваемого элемента управления в приложении iOS с одним представлением. Это учебник Swift 2, но до сих пор я делаю OK, перенося все на 3, когда я иду (я использую бета-версию XCode 8).
У меня есть собственный класс RatingControl
, связанный с View
в раскадровке.
В конструкторе класса я создаю кнопку:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.red()
Затем я пытаюсь назначить действие кнопке. В учебнике сказано, что я должен сделать это так:
button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(_:)),
for: .touchDown)
а затем создайте в том же классе RatingControl
метод:
func ratingButtonTapped(button: UIButton) {
print("Button pressed 👍")
}
Но когда я компилирую, он жалуется:
type "RatingControl" не имеет члена "ratingButtonTapped"
Я сделал 100% уверенность, что функция есть, в классе и правильно названа. Полный источник
Есть ли что-то очевидное, что мне не хватает?
Что я пробовал:
-
Добавлен @objc
к определению класса в соответствии с этим ответом (но это кажется странным для вещи только для Swift, нет?)
-
Сделано ratingButtonTapped()
явно public
(но это не похоже, что это необходимо)
-
Спрятано со строками вместо селекторов button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)
и еще много, но это просто сработает позже.
Ответы
Ответ 1
В Swift 3 ссылка метода для: func ratingButtonTapped(button: UIButton)
становится ratingButtonTapped(button:)
.
Таким образом, использование #selector(RatingControl.ratingButtonTapped(button:))
также работает.
И если вы хотите сохранить #selector(RatingControl.ratingButtonTapped(_:))
, вам нужно объявить метод ratingButtonTapped
как:
func ratingButtonTapped(_ button: UIButton) { //<- `_`
print("Button pressed 👍")
}
И если у вас есть только один метод ratingButtonTapped
в классе, вы можете указать селектор как #selector(RatingControl.ratingButtonTapped)
или просто (изнутри класса RatingControl
) #selector(ratingButtonTapped)
.
Ответ 2
Это произошло потому, что Swift 3 изменил способ обращения к первому имени параметра. В Swift 3 все имена параметров должны использоваться при вызове функции, если явным _
не было объявлено имя параметра.
То, что вы использовали в качестве селектора, было прекрасным, если вы заявили о своей функции как:
func ratingButtonTapped(_ button: AnyObject) {
print("Button pressed 👍")
}
Вы могли бы использовать это как ваш селектор:
#selector(RatingControl.ratingButtonTapped(button:))
Добавил @objc к определению класса в соответствии с этим ответом (но это кажется странно для вещи только для Swift, нет?)
Ваш код может быть в Swift, но вы взаимодействуете со временем выполнения Objective-C при кодировании Cocoa Touch (инфраструктура iOS). Селектор - это функция, которая должна быть видимой для среды выполнения Objective-C. Вы получаете это бесплатно большую часть времени, потому что вы реализуете это в классе, который в конечном итоге наследует от NSObject
(например, UIViewController
). Если у вас есть только класс Swift, который не наследуется от NSObject
, вы можете добавить @objc
, чтобы класс и методы были видимыми для среды выполнения Objective-C.
Ответ 3
Если вы хотите вызвать действие, которое находится в вашем контроллере просмотра из другого класса, вы можете попробовать это.
Используйте ViewController() для своей цели. Используйте ViewController.functionName для вашего селектора. Не используйте вспомогательный метод для переменной контроллера вида, например "vc", иначе вы не сможете получить доступ к объектам в ViewController.
Вот пример цели:
self.addTarget(ViewController(), action:#selector(ViewController.Test(_:)), for: UIControlEvents.touchDragInside)
В вашем контроллере просмотра приведен пример Action
@IBAction func Test(_ sender: Any?) {
print("Goodtime was here")
}
В цель вы должны добавить(), но не в селектор действий. Вам не нужно вызывать @IBAction, это может быть просто func. Некоторые люди используют @objc или публикацию любого из этих префиксов в действии должны работать.
Просмотрите, если действие находится в другом классе или ViewController, вы должны поместить ссылку на класс как в целевой, так и в селектор действий. В противном случае он будет пытаться всегда вызывать действие в одном файле независимо от того, правильно ли оно указано в Селекторе. Аналогично, если действие используется в одном и том же файле, self для цели и внутри селектора действий.
Приветствия
Ответ 4
При добавлении целей кнопки в начале 5 сначала вам нужно быть в class
.
class SomeClass {
// ...
let button = UIButton()
// configure button to taste...
button.addTarget(self,
action: #selector(doSomething),
for: .touchUpInside)
// ...
@objc public func doSomething() {
print("hello, world!")
}
// ...
}