0

Текущий прогрессДобавлено UITableViewCell GestureRecognizer Делегат Не рабочая

У меня есть таблица, где салфетки жест должен принести новый ViewController. Он действительно работает и может вызывать segue и загружать новый VC (весь код ниже, должен быть полезен для всех, кто хочет добавить жест).

Проблема

Но я хочу передать новое ViewController значение индекса в спер-клетки, и я был не в состоянии сделать это или повторить методы в руководствах, которые я нашел.

В моей таблице используется собственный класс ячеек, в котором добавлен жест. Жест добавлен, я его протестировал, и он использует делегат для запуска функции в главном VC и запускает segue.

Ошибка, похоже, происходит в самом начале, когда я пытаюсь захватить начального отправителя и передать его через делегата.

Код

Вот код моего пользовательского ячейки:

class CustomTableViewCell: UITableViewCell { 

@IBOutlet var nameLabel: UILabel! 
@IBOutlet var descLabel: UILabel! 

var delegate: mainViewDelegate! 

override func awakeFromNib() { 
    super.awakeFromNib() 
    // Initialization code 

    //Create 'swipeLeft' variable, provide action (swipedLeft) and add to cell 
    let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "swipedLeft") 
    swipeLeft.direction = UISwipeGestureRecognizerDirection.Left 
    self.addGestureRecognizer(swipeLeft) 

} 

override func setSelected(selected: Bool, animated: Bool) { 
    super.setSelected(selected, animated: animated) 
    // Configure the view for the selected state 
} 

func swipedLeft (sender: UISwipeGestureRecognizer) { 
    println("swipe detected, cell function run") 
    if(self.delegate != nil){ 
     self.delegate.cellSwipedLeft(sender) 
    } 
} 
} 

Протокол:

protocol mainViewDelegate { 
    func cellSwipedLeft (UISwipeGestureRecognizer) 
} 

Главная ViewController Заголовок:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, mainViewDelegate { 

И я также добавил необходимый делегат строку в функции cellForRowAtIndexPath главного ВК:

func tableView... 
... (edited out to save space) 
cell.delegate = self 
} 

Основная функция VC:

func cellSwipedLeft (sender: UISwipeGestureRecognizer) { 
    println("cellSwipedLeft main VC func ran") 
    performSegueWithIdentifier("modalTo_HomeTaskAction", sender: nil) 
} 

Теперь все это работает, если я ничего не передавая в параметрах, но когда я добавляю UISwipeGestureRecognizer, он терпит неудачу с ошибкой SIGABRT Thread 1: signal. Моя цель состоит в том, чтобы пройти этот жест успешно, то я добавлю код ниже, чтобы получить индекс и использовать prepareForSegue, чтобы передать его в мои КИ:

let gesture = sender as! UISwipeGestureRecognizer 
let cell = gesture.view! as! CustomTableViewCell_F2 
let indexPath = tableView.indexPathForCell(cell) 

Так что большой вопрос, почему, проходящий через UISwipeGestureRecognizer получить меня ошибка, которые начинаются так:

2015-08-21 03:23:39.566 AppName[10170:945334] -[AppName.CustomTableViewCell swipedLeft]: unrecognized selector sent to instance 0x7fb149766560 
2015-08-21 03:23:39.619 AppName[10170:945334] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [AppName.CustomTableViewCell swipedLeft]: unrecognized selector sent to instance 0x7fb149766560' 
*** First throw call stack: 
(
    0 CoreFoundation       0x0000000106dfcc65 __exceptionPreprocess + 165 
1 libobjc.A.dylib      0x0000000108ba9bb7 

ответ

1

Дэйв, вот простой способ сделать это, это без протоколов, а вместо этого мы используем блоки.в пользовательской UITableViewCell, мы делаем это:

SETUP:

import Foundation 
import UIKit 

class EXTableViewCell: UITableViewCell { 
    @IBOutlet var nameLabel: UILabel! 
    @IBOutlet var descLabel: UILabel! 
    var doWork: (() -> Void)? 
    func swipedLeft (sender: UISwipeGestureRecognizer) { 
     if let callback = self.doWork { 
      println("swipe detected, cell function run") 
      callback() 
     } 
    } 
    override func awakeFromNib() { 
     super.awakeFromNib() 
     let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "swipedLeft") 
     swipeLeft.direction = UISwipeGestureRecognizerDirection.Left 
     self.addGestureRecognizer(swipeLeft) 
    } 
    override func setSelected(selected: Bool, animated: Bool) { 
     super.setSelected(selected, animated: animated) 
    } 
} 

Пользовательские ViewController:

import UIKit 

class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 
    override func viewWillAppear(animated: Bool) { 
     super.viewWillAppear(animated) 
    } 
    override func viewDidLoad() { 
     super.viewDidLoad() 
    } 
    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 
    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return 0 //replace with the correct info 
    } 
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return 4 //replace with the correct info 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! FFViewCell 
      cell.doWork = { 
      () -> Void in 
       self.doStuff(indexPath.row) 
     } 
      cell.labelMessage.text = items[indexPath.row] as String 
      return cell 
     } 
     func doStuff(integer: NSInteger) { 
      println("i got here \(integer)") 
     } 
} 

Как это работает:

Вы видите, мы объявляя свойство блока, которое позволяет нам передать пустой вызов функции (PER SE) на любой «EXTable» ViewCell ", который вы создаете в своем UIViewController.

Так, в обычае UITableViewCell, мы объявляем свойство пустоты блока:

var doWork: (() -> Void)? 

Мы придаем сенсорный обработчик клетку:

func swipedLeft (sender: UISwipeGestureRecognizer) { 
     if let callback = self.doWork { 
      println("swipe detected, cell function run") 
      callback() 
     } 
    } 

Затем мы называем в этот обработчик внутри или основных UIViewController и установить это свойство при настройке нашего вида таблицы. Клетки:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! EXTableViewCell 
     cell.doWork = { 
      () -> Void in 
      self.doStuff() 
     } 
     return cell 
    } 

Спецификация fically:

cell.doWork = { 
      () -> Void in 
      self.doStuff() 
     } 

Мы, очевидно, затем настроить функцию «DoStuff» делать то, что мы хотим сделать в нашем UIViewController:

func doStuff() { 
     println("i got here") 
    } 

Нет протоколов, не беспорядок, не завинчивания вокруг с созданием делегации происходят, все функции, основанные на блоках. Я не тестировал этот код с фактическим UIViewController, однако это работает безупречно в Objective-C и перед публикацией этого кода я убедился, что он компилируется.

Как быстрая заметка об огромности блоков, почти все, что кажется супер сложным с делегированием и протоколами, может быть выполнено с помощью блоков, жесткая часть используется для использования блоков и понимания их универсальности. Вероятно, наиболее приятной является тот факт, что вы можете использовать «свойства блока», как обычное свойство, но с дополнительным преимуществом присоединения события обработчика к объекту, которому принадлежит свойство блока. Во всяком случае, еще одна вещь, которую вы, возможно, придется сделать это, но это просто:

Вам может понадобиться, чтобы начать свой собственный вид ячейки таблицы, как это так, что делает его делегатом UIGestureRecognizer так:

class EXTableViewCell: UITableViewCell, UIGestureRecognizerDelegate { 

и вам, возможно, придется объявить жест распознаватель в классе настраиваемой таблицы вида клеток, так это выглядит примерно так:

swipeLeft.delegate = self 
swipeLeft.cancelsTouchesInView = false 

Кроме того, если у вас есть проблемы, делая это произойдет, то дайте мне знать, я буду видеть если я не могу просто получить полную реализацию для этого.

Рабочий пример, испытания и готов к работе:

Пользовательские tableViewCell:

import Foundation 
import UIKit 

class FFViewCell: UITableViewCell, UIGestureRecognizerDelegate { 

    var labelMessage = UILabel() 

    var doWork: (() -> Void)? 

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
     super.init(style: style, reuseIdentifier: reuseIdentifier) 
     let swipeLeft: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "this") 

     swipeLeft.delegate = self 
     swipeLeft.cancelsTouchesInView = false 

     self.addGestureRecognizer(swipeLeft) 

     labelMessage.setTranslatesAutoresizingMaskIntoConstraints(false) 
     contentView.addSubview(labelMessage) 
     var viewsDict = ["labelMessage" : labelMessage] 

     contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[labelMessage]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)) 
     contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[labelMessage]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)) 

    } 
    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
    func this() { 
     if let callback = self.doWork { 
      println("swipe detected, cell function run") 
      callback() 
     } 
    } 

} 

AppDelegate:

import UIKit 

@UIApplicationMain 

class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 
    var rootViewController: UINavigationController? 
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     window = UIWindow(frame: UIScreen.mainScreen().bounds) 

     rootViewController = UINavigationController(rootViewController: ViewController()) 
     if let window = window { 
      window.backgroundColor = UIColor.whiteColor() 

      window.rootViewController = rootViewController 

      window.makeKeyAndVisible() 
     } 
     return true 
    } 
    func applicationWillResignActive(application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    } 

    func applicationWillEnterForeground(application: UIApplication) { 
     // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
    } 

    func applicationDidBecomeActive(application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    } 

    func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    } 


} 

ViewController:

import UIKit 

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 

    var tableView : UITableView? 
    var items = ["asdf","asdf","asdf","asdf","asdf"] 

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 
     super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 
    } 
    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView = UITableView(frame: CGRectMake(0, 0, 414, 736), style: UITableViewStyle.Plain) 
     tableView!.delegate = self 
     tableView!.dataSource = self 
     tableView!.registerClass(FFViewCell.self, forCellReuseIdentifier: "Cell") 
     self.view .addSubview(tableView!) 
    } 
    override func loadView() { 
     var stuf = UIView() 
     stuf.frame = CGRectMake(0, 0, 414, 736) 
     stuf.backgroundColor = UIColor .redColor() 
     self.view = stuf 
    } 
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return items.count; 
    } 
    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return 1 
    } 
    func tableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat 
    { 
     return 44 
    } 
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! FFViewCell 
     cell.doWork = { 
      () -> Void in 
      self.doStuff() 
     } 
     cell.labelMessage.text = items[indexPath.row] as String 
     return cell 
    } 
    func doStuff() { 
     println("i got here") 
    } 
} 

Вот «коромысло gesture ", Dave:

import Foundation 
import UIKit 

class FFViewCell: UITableViewCell, UIGestureRecognizerDelegate { 

    var labelMessage = UILabel() 

    var doWork: (() -> Void)? 

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
     super.init(style: style, reuseIdentifier: reuseIdentifier) 
     let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "this") 
     swipeLeft.direction = UISwipeGestureRecognizerDirection.Left 
     swipeLeft.delegate = self 
     swipeLeft.cancelsTouchesInView = false 
     self.addGestureRecognizer(swipeLeft) 

     labelMessage.setTranslatesAutoresizingMaskIntoConstraints(false) 
     contentView.addSubview(labelMessage) 
     var viewsDict = ["labelMessage" : labelMessage] 

     contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[labelMessage]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)) 
     contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[labelMessage]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict)) 

    } 
    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
    func this() { 
     if let callback = self.doWork { 
      println("swipe detected, cell function run") 
      callback() 
     } 
    } 

} 
+0

Larcerax, спасибо. Эта вещь блока совершенно для меня совершенно. Что означает пустота? Кроме того, теперь я получаю индексный путь, просто ссылаясь на переменную 'cell'? Я обязательно попробую это, но хочу быть бодрым. Здесь почти 6 утра, и я работаю над этим всю ночь, поэтому примерно через 8-10 часов я дам вам знать, если это сработает. Спасибо –

+0

Да, так что вы можете ссылаться на ячейку так же, как вы делаете, более чем вероятно, а «void» просто означает, что нет никакого возвращаемого значения, это просто funciton, который работает, и вот так. – Loxx

+0

У меня, вероятно, будет решение, полностью в течение следующих 2 часов, поэтому, когда вы встаете и пробудитесь, повторите проверку – Loxx

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