当前进度
我有一个表格,其中滑动手势应该调出一个新的ViewController。它实际上工作,可以调用segue并加载新的VC(下面的所有代码,应该对任何想要添加手势的人都有帮助)。
问题
但我想将新的ViewController传递给swiped-cell的索引值,而我一直无法做到这一点,或者复制了我发现的指南中解释的方法。
我的表使用自定义单元格类,这是添加手势的位置。添加了手势,我测试了它,它确实使用委托触发主VC中的功能并触发segue。
当我尝试捕获初始发件人并将其传递给委托时,错误肯定会在开始时发生。
代码
这是我的自定义单元格代码:
bool compare_and_swap(unsigned int* var, unsigned int oldval, unsigned int newval)
{
// Move the old value into register _AREG_CCV because this is the register
// that var will be compared against
_Asm_mov_to_ar(_AREG_CCV, oldval);
// Do the compare and swap
return oldval == _Asm_cmpxchg(
_SZ_W /* 4 byte word */,
_SEM_ACQ /* acquire the semaphore */,
var,
newval,
_LDHINT_NONE /* locality hint */);
}
协议:
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)
}
}
}
主ViewController标题:
protocol mainViewDelegate {
func cellSwipedLeft (UISwipeGestureRecognizer)
}
我还在主VC的cellForRowAtIndexPath函数中添加了所需的委托行:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, mainViewDelegate {
主要的VC功能:
func tableView...
... (edited out to save space)
cell.delegate = self
}
现在,如果我没有在参数中传递任何内容,那么所有这些都可以工作,但是当我添加UISwipeGestureRecognizer时,它会因为线程1:信号SIGABRT错误而失败。我的目标是成功传递手势,然后我将添加以下代码以获取索引并使用prepareForSegue将其传递给我的VC:
func cellSwipedLeft (sender: UISwipeGestureRecognizer) {
println("cellSwipedLeft main VC func ran")
performSegueWithIdentifier("modalTo_HomeTaskAction", sender: nil)
}
所以最大的问题是,为什么传递UISwipeGestureRecognizer会给我一个错误,就像这样:
let gesture = sender as! UISwipeGestureRecognizer
let cell = gesture.view! as! CustomTableViewCell_F2
let indexPath = tableView.indexPathForCell(cell)
答案 0 :(得分:1)
戴夫,这是一个更简单的方法,这是没有协议,而是我们使用块。在您的自定义UITableViewCell中,我们这样做:
设置:
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)到任何" EXTableViewCell"你在UIViewController中创建的。
因此,在自定义UITableViewCell中,我们声明了一个void block属性:
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
}
具体做法是:
cell.doWork = {
() -> Void in
self.doStuff()
}
然后我们显然设置了" doStuff"函数在我们的UIViewController中执行我们想要它做的事情:
func doStuff() {
println("i got here")
}
没有协议,没有混乱,没有搞定委托发生,所有基于块的功能。我没有使用实际的UIViewController测试此代码,但是,这确实在Objective-C中完美运行,在发布此代码之前,我确保它编译。</ p>
作为对块的可怕性的快速说明,几乎所有看似超级复杂的委托和协议都可以通过块来完成,困难的部分是利用块来理解它们的多功能性。可能最令人愉快的部分是你可以使用&#34;阻止属性&#34;就像一个普通的属性,但附加的好处是将一个处理程序事件附加到拥有该块属性的对象。无论如何,你可能需要做的另一件事是,但这很简单:
您可能需要像这样启动自定义表格视图单元格,使其成为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")
}
}
这是&#34;轻扫手势&#34;代码,戴夫:
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 ()
}
}
}