Swift:如何将NSIndexPath绑定到addTarget

时间:2015-04-06 18:51:32

标签: ios swift

我在每个动态创建的行中都有UISwitch,我希望将NSIndexPath绑定到addTarget选择器。

我曾考虑过允许用户点击该行以切换开关,但从UX的角度来看,让开关处理此方法更有意义,因此使用didSelectRowAtIndexPath不是一个合适的解决方案。

当我的单元格被创建时,我当前绑定了一个这样的选择器:

// Create listener for each switch
prefCell.subscribed?.addTarget(self, 
                               action: "switchFlipped:",
                               forControlEvents: UIControlEvents.ValueChanged)

调用相应的方法:

func switchFlipped(flipSwitch: UISwitch, indexPath: NSIndexPath) {}

显然这会引发错误,因为NSIndexPath不是有效的引用,因为我相信它只会发送按钮引用。有什么办法可以绑定索引路径吗?如果没有,有没有办法从UISwitch

的上下文中获取当前单元格

7 个答案:

答案 0 :(得分:4)

目标 - 动作模式不允许任意选择器。您可以拥有f(sender:)f(sender:event:)。两个人都不会帮助你。但是您可以使用代码来计算函数中的indexPath。

代码应该是自我解释的:

func switchFlipped(flipSwitch: UISwitch) {
    let switchOriginInTableView = flipSwitch.convertPoint(CGPointZero, toView: tableView)
    if let indexPath = tableView.indexPathForRowAtPoint(switchOriginInTableView) {
        println("flipped switched at \(indexPath)")
    }
    else {
        // this should not happen
    }
}

答案 1 :(得分:1)

您可以根据需要尝试3种方法。

  1. 创建自定义UISwitch类并向其添加NSIndexPath属性。收到通知后,键入cast到您的自定义类并访问NSIndexPath。
  2. 创建一个自定义UITableViewCell类并将NSIndexPath保存到它。当您收到UISwitch的通知时,获取其超级视图并查看哪个是您的customUITableViewCell实例并获取该属性。
  3. 如果您只有一个部分,则表示您需要担心的是行。将UISwitch标记设置为行号,并在切换开关时访问它。
  4. 最科技的解决方案使用Swift扩展。
  5.   

    扩展程序为现有的类,结构或枚举类型添加新功能。这包括扩展您无权访问原始源代码的类型的功能   Apple Docs

答案 2 :(得分:1)

这应该是一个很好的解决方案,而不是取决于某一点。您调用Switch的超级视图,因此计算单元格的索引路径。

func switchTapped(sender: UISwitch) -> NSIndexPath {
    let cell = sender.superview!.superview! as UITableViewCell
    return tableView.indexPathForCell(cell)!
}

这可靠地起作用,这就是为什么你可以简单地解开任何选项。

答案 3 :(得分:1)

使用委托。

您的交换机的目标操作应该是自定义UITableViewCell中的方法。该自定义tableviewcell应该声明一个协议,tableview应该是它的委托。然后你的tableviewcell应该从switch的目标函数中调用它的委托方法。

tableviewcell的委托方法应该有一个参数,其中单元格传递self。然后在tableviewcontroller委托实现中,您可以使用indexPathForCell:

更新:

这是swift协议和代表的苹果文档:

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

简而言之,您需要定义协议

protocol CustomUITableViewCellDelegate {
    func tableViewCellSubscribed(cell: myCustomUITableViewCell) -> Void
}

然后你让你的tableviewcontroller类符合这个协议:

class myTableViewController: UITableViewController, CustomUITableViewCellDelegate {

func tableViewCellSubscribed(cell: myCustomUITableViewCell) -> Void {
    //this is where you handle whatever operations you want to do regarding the switch being valuechanged
}

// class definition goes here
}

然后你的自定义UITableViewCell类应该具有这样的委托属性:

class myCustomUITableViewCell : UITableViewCell {
    var delegate : CustomUITableViewCellDelegate?

    //class definition goes here
}

最后,在tableView:cellForRowAtIndexPath:中设置单元格的委托,你就可以了。您只需要在切换操作的目标方法中调用tableViewCellSubscribed:委托函数。

答案 4 :(得分:0)

我在很多项目中都使用过这种方法,你只需要在你的自定义单元格中添加一个回调,每次你的开关改变时,你都可以运行这个回调并在你的表数据源实现中捕获它,在一个污垢之下简单的例子。

1。创建UITableViewCell自定义类

// An example of custom UITableViewCell class

class CustomCell:UITableViewCell {

  required init(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }

  var onSwitchChange:() -> Void?

}

class TableDataSource:UITableViewDataSource {

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:CustomCell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as CustomCell
    cell.onSwitchChange = {
      NSLog("Table: \(tableView) Cell:\(cell) Index Path: \(indexPath)")
    }
  }
}

答案 5 :(得分:0)

实际上,Apple已经提供了API来获取indexPath。 就像这样(在Objective-C中)

NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

答案 6 :(得分:0)

更容易,您可以使用tag变量:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
    cell.mySwitch.tag = indexPath.item
    cell.mySwitch.addTarget(self, action: #selector(switchChanged), for: UIControlEvents.valueChanged)
    ...
}

func switchChanged(mySwitch: UISwitch) {
    let indexPathItem = mySwitch.tag
    ...
}

来自官方文件:

  

var tag:Int {get set}

     

一个整数,可用于标识您的视图对象   应用。

     

默认值为0.您可以设置此标记的值   然后使用该值来识别视图。