2017-01-11 3 views
1

Итак, я написал протокол, чтобы сделать все, что когда-либо было 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 { 
} 

Тогда я назвал функцию setGesutre в viewDidLoad из контроллер:

override func viewDidLoad() { 
    super.viewDidLoad() 

    draggableLabel.setGesture() 
} 

OK Я признаю, что не знаю, что я делаю.

ответ

1

Действие wasDragged(gesture:) должно быть доступно для отправки сообщений через среду выполнения Objective-C. Используйте аннотацию @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, подключите видоискатель к виду, которое вы хотите сделать перетаскиваемым.

 Смежные вопросы

  • Нет связанных вопросов^_^