公认的解决方案是一种巧妙的技巧。
但是,如果我们可以利用 UIView 上已有的tag 属性,为什么还需要使用命中点呢?您会说 标签只能存储行或部分,因为它是一个 Int。
嗯...不要忘记你的根源(CS101)。
单个 Int 可以存储两个大小小两倍的整数。
这是一个扩展:
extension Int {
public init(indexPath: IndexPath) {
var marshalledInt: UInt32 = 0xffffffff
let rowPiece = UInt16(indexPath.row)
let sectionPiece = UInt16(indexPath.section)
marshalledInt = marshalledInt & (UInt32(rowPiece) << 16)
marshalledInt = marshalledInt + UInt32(sectionPiece)
self.init(bitPattern: UInt(marshalledInt))
}
var indexPathRepresentation: IndexPath {
let section = self & 0x0000ffff
let pattern: UInt32 = 0xffff0000
let row = (UInt32(self) & pattern) >> 16
return IndexPath(row: Int(row), section: Int(section))
}
}
在您的tableView(_:, cellForRowAt:) 中,您可以:
cell.yourSwitch.tag = Int(indexPath: indexPath)
然后在动作处理程序中你可以:
func didToogle(sender: UISwitch){
print(sender.tag.indexPathRepresentation)
}
但请注意它的限制:行和节不能大于 65535。 (UInt16.max)
我怀疑您的 tableView 的索引会变得那么高,但如果他们这样做,挑战自己并实施更有效的打包方案。假设我们有一个非常小的部分,我们不需要所有 16 位来表示一个部分。我们可以有这样的 int 布局:
{section area length}{all remaining}[4 BITS: section area length - 1]
这是我们的 4 个 LSB 表示节区域的长度 - 1,假设我们为一个节分配了至少 1 位。因此,如果我们的部分为 0,则该行最多可以占用 27 位([1][27][4]),这绝对足够了。