使用协议

时间:2017-01-11 01:18:26

标签: ios swift swift-protocols

所以我编写了一个协议来制作符合可拖动性的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()
}

好的,我承认我不知道自己在做什么。

1 个答案:

答案 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,将视图插座连接到您想要拖动的视图。