如何在选择器中传递自定义UITableViewCell

时间:2017-10-03 18:22:53

标签: ios objective-c xcode uitableview

我有一个包含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设置一个不同的标签,但我想知道是否有更清洁的解决方案。

3 个答案:

答案 0 :(得分:4)

坏消息是你不能那样做......确切地说。

好消息是,在您的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将把该开关作为它的发送者参数。您可以从发件人处获取Switch的值。

答案 1 :(得分:0)

我相信你只能通过这样的选择器方法传递发件人。

您可以考虑将UISwitch方法放在自定义UITableViewCell类中,并为自定义类创建一个委托协议,将该单元传递给ViewController。

答案 2 :(得分:0)

我提出了另一个解决方案,但这也有点难看。我将单元格转换为发送者的超级视图的超级视图(UISwitch>>内容视图>>单元格)

HydrationNotificationTableViewCell *cell = (HydrationNotificationTableViewCell *)([senderSwitch superview].superview);

希望那里有一个更清洁的解决方案。