我在 ImageView 子类中定义手势识别器,但在 ViewController 中调用方法会因 "unrecognized selector" 而崩溃
I am defining gesture recognizers in an ImageView subclass but calling a method in the ViewController crashes with "unrecognized selector"
我在 ImageView 子 class 中定义手势识别器,但在 ViewController 中调用方法会因 "unrecognized selector" 而崩溃。如果我在 VC 中定义手势,手势会起作用,但我试图将代码放在自定义视图 class 中以减少混乱。
这可能吗?这就是我正在做的:
class DetailPhotoImageView: UIImageView {
func setupGestures(){
let tapped = UITapGestureRecognizer(target: self, action: #selector(TripDetailVC.tapped(_:)))
tapped.numberOfTapsRequired = 2
addGestureRecognizer(tapped)
}
}
然后在 VC 我有这个函数并调用 imageView.setupGestures()
func tapped(_ gesture:UIGestureRecognizer) {
if let tapGesture = gesture as? UITapGestureRecognizer {
switch tapGesture.numberOfTapsRequired {
case 2:
print("Worked")
default:
break
}
}
}
为你的 UIImageView 制定一个接受手势的协议,并将你的 ViewController 设置为委托(将 ImageView 作为参数也是一种很好的做法..或常见):
protocol DetailPhotoDelegate {
func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor gesture: UITapGestureRecognizer)
}
向您的 UIImageView 子类添加一个委托变量,并在点击视图时执行您的协议函数。另外,请确保您的 UIImageView 是 UIGestureRecognizerDelegate。
class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {
var delegate: DetailPhotoDelegate?
func setupGestures() {
let tap = UITapGestureRecognizer(target: self, action: #selector(someAction(_:)))
tap.delegate = self
tap.numberOfTapsRequired = taps
addGestureRecognizer(tap)
}
func someAction(_ guesture: UITapGestureRecognizer) {
print("tap - subclass func")
guard let aDelegate = aDelegate else { assertionFailure(); return }
delegate.detailPhoto(self, actionFor: gesture)
}
}
然后将协议添加到您的 ViewController,在执行操作之前的某处将其设置为您的 DetailPhotoImageView 的委托(例如,我在 viewDidLoad() 中完成),并实现协议方法愿望:
class ViewController: UIViewController, DetailPhotoDelegate {
@IBAction weak var detailPhoto: DetailPhotoImageView!
override func viewDidLoad() {
super.viewDidLoad()
detailPhoto.delegate = self
}
// Mark: DetailPhotoDelegate
func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor guesture: UITapGestureRecognizer) {
switch guesture.numberOfTapsRequired {
case 1: print("1 tap"); return
case 2: print("2 taps"); return
default: print("\(guesture.numberOfTapsRequired) taps"); return
}
}
我认为目标不应该是自己
所以按照 Randall Wang 的建议,他们是对的,你也可以换一种方式,space-省钱。将 viewController 作为参数传递并将其设置为目标:
class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {
func setupGestures(_ target: UIViewController) {
guard let aTarget = target as? MyViewController else { return }
let tap = UITapGestureRecognizer(target: aTarget, action: #selector(aTarget.someAction(_:)))
tap.delegate = self
tap.numberOfTapsRequired = taps
addGestureRecognizer(tap)
}
}
在你的 viewController class:
detailPhoto.setupGestures(self)
我在 ImageView 子 class 中定义手势识别器,但在 ViewController 中调用方法会因 "unrecognized selector" 而崩溃。如果我在 VC 中定义手势,手势会起作用,但我试图将代码放在自定义视图 class 中以减少混乱。
这可能吗?这就是我正在做的:
class DetailPhotoImageView: UIImageView {
func setupGestures(){
let tapped = UITapGestureRecognizer(target: self, action: #selector(TripDetailVC.tapped(_:)))
tapped.numberOfTapsRequired = 2
addGestureRecognizer(tapped)
}
}
然后在 VC 我有这个函数并调用 imageView.setupGestures()
func tapped(_ gesture:UIGestureRecognizer) {
if let tapGesture = gesture as? UITapGestureRecognizer {
switch tapGesture.numberOfTapsRequired {
case 2:
print("Worked")
default:
break
}
}
}
为你的 UIImageView 制定一个接受手势的协议,并将你的 ViewController 设置为委托(将 ImageView 作为参数也是一种很好的做法..或常见):
protocol DetailPhotoDelegate {
func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor gesture: UITapGestureRecognizer)
}
向您的 UIImageView 子类添加一个委托变量,并在点击视图时执行您的协议函数。另外,请确保您的 UIImageView 是 UIGestureRecognizerDelegate。
class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {
var delegate: DetailPhotoDelegate?
func setupGestures() {
let tap = UITapGestureRecognizer(target: self, action: #selector(someAction(_:)))
tap.delegate = self
tap.numberOfTapsRequired = taps
addGestureRecognizer(tap)
}
func someAction(_ guesture: UITapGestureRecognizer) {
print("tap - subclass func")
guard let aDelegate = aDelegate else { assertionFailure(); return }
delegate.detailPhoto(self, actionFor: gesture)
}
}
然后将协议添加到您的 ViewController,在执行操作之前的某处将其设置为您的 DetailPhotoImageView 的委托(例如,我在 viewDidLoad() 中完成),并实现协议方法愿望:
class ViewController: UIViewController, DetailPhotoDelegate {
@IBAction weak var detailPhoto: DetailPhotoImageView!
override func viewDidLoad() {
super.viewDidLoad()
detailPhoto.delegate = self
}
// Mark: DetailPhotoDelegate
func detailPhoto(_ detailPhoto: DetailPhotoImageView, actionFor guesture: UITapGestureRecognizer) {
switch guesture.numberOfTapsRequired {
case 1: print("1 tap"); return
case 2: print("2 taps"); return
default: print("\(guesture.numberOfTapsRequired) taps"); return
}
}
我认为目标不应该是自己
所以按照 Randall Wang 的建议,他们是对的,你也可以换一种方式,space-省钱。将 viewController 作为参数传递并将其设置为目标:
class DetailPhotoImageView: UIImageView, UIGestureRecognizerDelegate {
func setupGestures(_ target: UIViewController) {
guard let aTarget = target as? MyViewController else { return }
let tap = UITapGestureRecognizer(target: aTarget, action: #selector(aTarget.someAction(_:)))
tap.delegate = self
tap.numberOfTapsRequired = taps
addGestureRecognizer(tap)
}
}
在你的 viewController class:
detailPhoto.setupGestures(self)