我在每个动态创建的行中都有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
?
答案 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种方法。
扩展程序为现有的类,结构或枚举类型添加新功能。这包括扩展您无权访问原始源代码的类型的功能 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协议和代表的苹果文档:
简而言之,您需要定义协议
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)
我在很多项目中都使用过这种方法,你只需要在你的自定义单元格中添加一个回调,每次你的开关改变时,你都可以运行这个回调并在你的表数据源实现中捕获它,在一个污垢之下简单的例子。
// 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.您可以设置此标记的值 然后使用该值来识别视图。