所以我编写了一个协议来制作符合可拖动性的UIView。但是,当我在模拟器中测试它时,当我尝试拖动视图时它会崩溃。并在日志
中显示libc++abi.dylib: terminating with uncaught exception of type NSException
协议:
protocol Draggable {}
extension Draggable where Self: UIView {
func wasDragged (gestrue: UIPanGestureRecognizer) {
let translation = gestrue.translation(in: UIScreen.main.focusedView)
if let label = gestrue.view {
label.center = CGPoint(x: label.center.x + translation.x, y: label.center.y + translation.y)
}
gestrue.setTranslation(CGPoint.zero, in: UIScreen.main.focusedView)
}
func setGesture () {
let gesture = UIPanGestureRecognizer(target: UIScreen.main, action: Selector(("wasDragged:")))
self.addGestureRecognizer(gesture)
self.isUserInteractionEnabled = true
}
}
并且在自定义标签类中我遵守了它:
class DraggableLabel: UILabel, Draggable {
}
然后我在视图控制器的viewDidLoad中调用了setGesutre函数:
override func viewDidLoad() {
super.viewDidLoad()
draggableLabel.setGesture()
}
好的,我承认我不知道自己在做什么。
答案 0 :(得分:1)
需要通过Objective-C运行时为消息分派访问操作wasDragged(gesture:)
。使用@objc
注释使方法可用于消息调度。 NSObject子类的方法是自动@objc
方法。
坏消息是,这只适用于与Objective-C兼容的类或扩展。像你这样的协议扩展是不兼容的,所以你不能把动作方法放到这些扩展中。
您可以选择将此功能添加到子类或普通类扩展中:
extension DraggableLabel {
func wasDragged (gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: UIScreen.main.focusedView)
center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
gesture.setTranslation(CGPoint.zero, in: UIScreen.main.focusedView)
}
func setGesture () {
let gesture = UIPanGestureRecognizer(target: self,
action: #selector(wasDragged(sender:)))
self.addGestureRecognizer(gesture)
self.isUserInteractionEnabled = true
}
}
(请注意,我还将手势识别器的目标更改为视图而不是主屏幕。您是否打算使用响应程序链将事件传播到右视图?)
与面向协议的方法相比,明显的缺点是灵活性降低。如果这是一个问题,我会考虑课堂构成。创建一个封装手势识别器及其操作方法的类。给它一个视图属性,并在设置该属性时配置所有内容:
class DraggingBehavior: NSObject {
@IBOutlet var view: UIView? {
didSet {
guard let view = view else { return }
let gesture = UIPanGestureRecognizer(target: self, action: #selector(wasDragged(sender:)))
view.addGestureRecognizer(gesture)
view.isUserInteractionEnabled = true
}
}
func wasDragged(sender: UIGestureRecognizer) {
print("Was dragged")
// put the view translation code here.
}
}
@IBOutlet
使此类与Interface Builder兼容。在自定义对象中拖动,将其类设置为DraggingBehavior
,将视图插座连接到您想要拖动的视图。