Мне довелось увидеть это в боковой панели, у меня недавно была эта проблема.К сожалению, из-за ограничений времени выполнения Objective-C вы не можете использовать @objc для расширений протокола, я считаю, что этот вопрос был закрыт в начале этого года.
Проблема возникает из-за того, что добавление добавляется после согласования протокола, поэтому нет возможности гарантировать соответствие протокола протоколу. При этом можно использовать, чтобы вызвать метод в качестве селектора из любого подкласса NSObject и соответствует протоколу. Это чаще всего делается с делегацией.
Это означает, что вы можете создать пустой подклассу оболочки, которая соответствует протоколу, и использовать оболочку для вызова ее методов из протокола, определенного в оболочке, любые другие неопределенные методы из протокола могут быть переданы делегату. Существуют и другие аналогичные решения, которые используют частное расширение конкретного класса, такого как UIViewController, и определяют метод, который вызывает метод протокола, но они также привязаны к определенному классу, а не по умолчанию реализации определенного класса, который соответствует протокол.
Подумайте, что вы пытаетесь реализовать стандартную реализацию функции протокола, которая использует другие собственные функции протокола, чтобы определить значение для собственной реализации. гмм!
Протокол:
public protocol CustomViewDelegate {
func update()
func nonDelegatedMethod()
}
Вид:
Используйте делегат, и определить метод обертку для безопасного развернет метод делегата.
class CustomView: UIView {
let updateButton: UIButton = {
let button = UIButton(frame: CGRect(origin: CGPoint(x: 50, y: 50), size: CGSize(width: 150, height: 50)))
button.backgroundColor = UIColor.lightGray
button.addTarget(self, action: #selector(doDelegateMethod), for: .touchUpInside)
return button
}()
var delegate:CustomViewDelegate?
required init?(coder aDecoder: NSCoder) {
fatalError("Pew pew, Aghh!")
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(updateButton)
}
@objc func doDelegateMethod() {
if delegate != nil {
delegate!.update()
} else {
print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
}
}
}
ViewController:
Соответствует в View Controller для делегата отображения вида: и реализовать метод Протокола.
class ViewController: UIViewController, CustomViewDelegate {
let customView = CustomView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))
override func viewDidLoad() {
super.viewDidLoad()
customView.backgroundColor = UIColor.red
customView.delegate = self //if delegate is not set, the app will not crash
self.view.addSubview(customView)
}
// Protocol -> UIView Button Action -> View Controller's Method
func update() {
print("Delegating work from View that Conforms to CustomViewDelegate to View Controller")
}
//Protocol > View Controller's Required Implementation
func nonDelegatedMethod() {
//Do something else
}
}
Обратите внимание, что контроллер представления только должен был соответствовать делегату и не ставил селектор некоторого свойства точки зрения, это разделяет точку зрения (и это протокол) от вида контроллера.
У вас уже есть UIView с именем TapView, который наследуется от UIView и Tappable так что ваша реализация может быть:
Протокол:
protocol TappableViewDelegate {
func tapGestureDetected(gesture:UITapGestureRecognizer)
}
TappableView:
class TappableView: UIView {
var delegate:TappableViewDelegate?
required init?(coder aDecoder: NSCoder) {
fatalError("Pew pew, Aghh!")
}
override init(frame: CGRect) {
super.init(frame: frame)
let gesture = UITapGestureRecognizer(target: self, action: #selector(doDelegateMethod(gesture:)))
addGestureRecognizer(gesture)
}
@objc func doDelegateMethod(gesture:UITapGestureRecognizer) {
if delegate != nil {
delegate!.tapGestureDetected(gesture: gesture)
} else {
print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
}
}
}
ViewController:
class ViewController: UIViewController, TappableViewDelegate {
let tapView = TappableView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))
override func viewDidLoad() {
super.viewDidLoad()
tapView.backgroundColor = UIColor.red
tapView.delegate = self
self.view.addSubview(tapView)
}
func tapGestureDetected(gesture: UITapGestureRecognizer) {
print("User did tap")
}
}
Не могли бы вы опубликовать компилируемый пример? Как объявляется 'panGestureDetected'? – Sulthan
Я собираюсь добавить его завтра, спасибо Sulthan – Andrea
@Andrea Изменить Pannable.panGestureDetected (_ :). введите имя класса, в котором объявлен panGestureDetected, вместо 'Pannable.whatever' просто введите' YourClass.panGestureDetected (_ :) ' –