2016-07-08 3 views
3

У меня есть большой UITableViewCell, в котором есть 2 пользовательских UIViews. Один из них должен позволять взаимодействие (выбор и отбор), а одно из представлений не должно допускать взаимодействия.Предотвращение взаимодействия при подсмотре UITableViewCell

Я знаю, что я могу включить или отключить взаимодействие во всей ячейке или в каждом из подзонов, но если я отключу взаимодействие в UIView, ячейка по-прежнему будет выбрана или отменена.

Есть ли способ, например, разрешить касания в верхней половине ячейки, а не на дне?

Вот скриншот UITableViewCell я описал

enter image description here

ответ

1

Я полностью согласен с JAL, вам нужно просмотреть всю структуру вашей ячейки, но я также знаю, что иногда и в некоторых случаях невозможно делать рефакторинг.

Так что, я думаю, что это, предположим, что у вас есть CustomTableViewCell составленное двумя видами, названный, например view1 и view2:

Код:

class MyView1 : UIView { 
    var isTouched : Bool = false 
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     self.isTouched = true 
     self.nextResponder()?.touchesBegan(touches, withEvent: event) 
    } 
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     self.isTouched = false 
     self.nextResponder()?.touchesEnded(touches, withEvent: event) 
    } 
} 
class MyView2 : UIView { 
    var isTouched : Bool = false 
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     self.isTouched = true 
     self.nextResponder()?.touchesBegan(touches, withEvent: event) 
    } 
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     self.isTouched = false 
     self.nextResponder()?.touchesEnded(touches, withEvent: event) 
    } 
} 
class CustomTableViewCell: UITableViewCell { 
    @IBOutlet weak var myExampleLabel: UILabel! 
    @IBOutlet weak var view1: MyView1! 
    @IBOutlet weak var view2: MyView2! 

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     print("situation: myView1 : \(self.view1.isTouched) myView2: \(self.view2.isTouched)") 
     var responder : UIResponder! = self 
     while responder.nextResponder() != nil { 
      responder = responder.nextResponder() 
      if responder is SimpleTableView.ViewController { // the name of your tableView delegate class 
       let vc = responder as! ViewController 
       let indexPath = vc.tableView.indexPathForCell(self) 
       vc.tableView(vc.tableView, didSelectRowAtIndexPath: indexPath!) 
      } 
     } 
     super.touchesBegan(touches, withEvent: event) 
    } 
} 

К другой стороне, где вы есть, например, UIViewController с UITableView:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 
    @IBOutlet var tableView: UITableView! 
    var items: [String] = ["We", "Heart", "Swift", "So", "Much"] 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView.delegate = self 
     tableView.dataSource = self 
     tableView.rowHeight = UITableViewAutomaticDimension 
     tableView.estimatedRowHeight = 140.0 
     self.tableView.registerNib(UINib(nibName: "CustomTableViewCell", bundle:nil), forCellReuseIdentifier: "CustomTableViewCell") 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return self.items.count; 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell", forIndexPath: indexPath) as! CustomTableViewCell 
     cell.myExampleLabel.text = self.items[indexPath.row] 
     return cell 
    } 

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
     let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomTableViewCell 
     print("row = %d",indexPath.row) 
     if cell.view1.isTouched { 
      print("tableView: touched view 1") 
      // do whatever you want with cell.view1 
      // if you want you can disable cell.view2.userInteractionEnabled 
     } 
     else { 
      print("tableView: touched view 2") 
      // same thing for cell.view2 
     } 
    } 
} 

Некоторые важные вещи:

Не забудьте установить правильный пользовательский класс для двух точек зрения, как описано в этой картине:

enter image description here

+0

Ссылка для загрузки проекта: http://s000.tinyupload.com/?file_id=00948862908688472208 –

0

вы можете переадресовать или отменить штрихи попаданию теста

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 
     if let hitView = super.hitTest(point, withEvent: event) { 
      if hitView.isKindOfClass(CustomSubviewClass) { 
       return nil 
      } else { 
       return hitView 
      } 
     } else { 
      return nil 
     } 
    } 
+0

вы предлагаете осуществить это в UITableView или в одном из подсмотров? В любом случае это происходит с EXC_BAD_ACCESS – mattgabor

2

Я бы сказал, что есть недостаток в вашей реализации, или что у вас есть проблема X/Y. Рассмотрим разделение одной ячейки на две отдельные ячейки и отключение выбора в нижней ячейке.

Если вы должны двигаться вперед с этой реализацией, рассмотрите возможность отключения выбора по всей ячейке. Поместите распознаватель жестов в верхнее подразделение, а при касании вручную вызовите didSelectRowAtIndexPath:.

0

Один из способов сделать эту работу - обходить методы UITableViewDelegate и использовать IBAction с помощью специального обработчика обратного вызова в ячейке.

  1. Установите Выбор типа для ячейки в None, чтобы предотвратить клетки от быть выбран/не выбран при нажатии на него.
  2. Убедитесь, что UITableViewDelegate не выполняет tableView:didSelectRowAtIndexPath.
  3. Добавить представление кнопки в ячейку и поместить ее так, чтобы она охватывала область, с которой вы хотите взаимодействовать.
  4. Добавить @IBAction func buttonTapped(sender: UIButton) в подкласс UITableViewCell.
  5. Добавьте переменную замыкания в ячейку. Вызовите закрытие при нажатии кнопки.
  6. В методе делегата tableView:cellForRowAtIndexPath: установить замыкание на ячейку для обработки вызова.

Пример UITableViewCell подкласса:

class MyTableViewCell: UITableViewCell { 

    var selectionHandler: ((Void) -> Void)? 

    override func prepareForReuse() { 
     // Remove the closure when the cell is recycled. 
     selectionHandler = nil 
    } 

    @IBAction func buttonTapped(sender: UIButton) { 
     // Call the closure when the button is tapped. 
     selectionHandler?() 
    } 
} 

В вашей UITableViewController:

class MyTableViewController: UITableViewController { 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let cell = .... 

     // Set the closure to be called when the button is tapped. 
     // Using weak self here to prevent a retain cycle. 
     cell.selectionHandler = { [weak self] in 
      self?.selectedCellAtIndexPath(indexPath) 
     } 

     return cell 
    } 

    // We are not using didSelectRowAtIndexPath 
    // override func tableView(tableView: UITableView, didSelectRowAtIndexPath: NSIndexPath) { 
    // } 
} 

Я не проверял этот код, чтобы он не может скомпилировать, хотя он должен служить для иллюстрации концепции.

0

Из редактора свойств таблицы, набор Selection значение No Selection или сделать это программно. Отключить взаимодействие в каждом из подзонов, за исключением того, что вы хотите действия subview. Возможно, передайте значение строки indexPath для этого поднабора в качестве тега. Или подкласс, который подсматривает с UIView для хранения информации indexPath.Затем реализуйте жестов перехода к этому подзону и выполните свое действие желания по методу распознавания жестов. Надеюсь, они должны делать то, что вы хотите.