如何在选择器中传递自定义 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

如何在 jquery 选择器中传递 php 变量值?

如何在 iOS 客户端中传递 AWS AppSync 自定义请求标头?

将一个水龙头从 UIScrollView 传递到其父视图