如何在选择器中传递自定义 UITableViewCell
Posted
技术标签:
【中文标题】如何在选择器中传递自定义 UITableViewCell【英文标题】:How to pass custom UITableViewCell in a selector 【发布时间】:2017-10-03 18:22:52 【问题描述】:我有一个包含 UISwitch 和 UILabel 的自定义 UITableViewCell。轻按开关后,我想知道哪个单元格的开关已激活/停用。
我的 cellForRowAtIndexPathMethod 中有以下代码,用于将目标添加到我的单元格的 UISwitch:
[cell.notifSwitch addTarget:self action:@selector(switchChangedFromCell:) forControlEvents:UIControlEventValueChanged];
这里是选择器的代码:
- (void)switchChangedFromCell:(id)sender
HydrationNotificationTableViewCell *cell = (HydrationNotificationTableViewCell *)sender;
if ([cell.notifSwitch isOn])
NSLog(@"Notification for %@ has been activated", cell.notifLabel.text);
else
NSLog(@"Deactivated notification %@", cell.notifLabel.text);
马上我相信我将发送者作为一个单元格是错误的,因为发送者确实是单元格中的 UISwitch。我也想知道如何传递单元格本身,以便知道哪个单元格已更改。
一种解决方案是在我的 cellForRowAtIndexPath 方法中为每个 UISwitch 设置不同的标签,但我想知道是否有更清洁的解决方案。
【问题讨论】:
如果你想获得你添加了 UISwitch 的 UITableViewCell 的引用,你可以使用 "testSwitch?.superview as?HydrationNotificationTableViewCell" 是的,我刚刚发布了一个答案,但我想我会继续为 UITableView 创建一个类别 Ya @Duncan C's answer是一个不错的选择,如果您想使用任何其他选项,您可以为 UISwitch 创建自定义类并在其中和 cellForRow:AtIndexPath 添加 NSIndexPath 类型的属性您可以将索引路径分配给 switch 属性,在目标上您也可以通过这种方式获取 indexPath,我希望它也是一个不错的选择。 这也是另一个不错的选择。我很感激! 谢谢,这一切都基于我们个人的兴趣和方法的风格,您可以根据需要使用更好的选择,但最终两种解决方案都会给您正确的答案。 【参考方案1】:坏消息是你不能这样做……完全正确。
好消息是,在您的 IBAction 中,UISwitch
是发件人,您可以使用它来确定哪个单元格包含 UISwitch
。
我在 Github 上有一个名为 TableViewExtension 的项目,它展示了如何做到这一点。
唯一真正的技巧是这个 UITableView 的扩展:
public extension UITableView
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath?
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
如果您添加该扩展,您可以让您的 IBAction 使用发送方来确定哪个控件触发了点击,并调用该方法来确定哪个单元格包含该控件:
@IBAction func controllTriggered(_ sender: UISwitch)
guard let indexPath = tableView.indexPathForView(sender) else return
//Now you have the indexPath of the cell containing `sender`
编辑:
请注意,在您的代码中,您尝试获取单元格,然后查询单元格的不同子视图以获取状态数据。不要那样做。您应该将状态数据存储在模型对象中。单元格用于显示信息并与用户交互。
如果用户点击一个开关,IBAction 将把开关作为它的 sender 参数。您可以从发送方获取 Switch 的值。
【讨论】:
啊,这很有趣。当我使用 Objective-C 时,我可以在 UITableView 上创建一个类别并转换这个 swift 代码。谢谢! 哦,对不起。我错过了那一点。是的,在我切换到 Swift 之前,我对 Objective-C 有类似的类别。 你是对的 - 我的架构已经关闭。我将为单元格的名称和 switchStatus 创建模型来填充数据而不是单元格状态。【参考方案2】:我相信你只能在这样的选择器方法中传递发件人。
您可以考虑将 UISwitch 方法放在您的自定义 UITableViewCell 类中,并为您的自定义类创建一个委托协议,将单元格传递给您的 ViewController。
【讨论】:
【参考方案3】:我想出了另一个解决方案,但这也有点难看。我将单元格投射到发送者的超级视图的超级视图(UISwitch >> 内容视图 >> 单元格)
HydrationNotificationTableViewCell *cell = (HydrationNotificationTableViewCell *)([senderSwitch superview].superview);
希望有更清洁的解决方案。
【讨论】:
以上是关于如何在选择器中传递自定义 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Xamarin IOS 自定义渲染器中单击 UITextField Rightview 打开 UIPickerView