gpt4 book ai didi

ios - 表格 View 单元格复选标记在滚动时更改位置

转载 作者:行者123 更新时间:2023-11-28 15:18:56 25 4
gpt4 key购买 nike

我是 Swift 的新手。我在表格 View 中创建了一个简单的列表。当用户长按一行时,该行将被选中。它工作得很好。但是当我向下滚动时,复选标记改变了它的位置。我还尝试在 NSMutableSet 中存储位置。但它仍然不起作用。也许我做错了什么。

这是我的代码:

此方法在长按时被调用。

func longpress(gestureRecognizer: UIGestureRecognizer)
{
let longpress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longpress.state
let locationInview = longpress.location(in: tableview1)
var indexpath=tableview1.indexPathForRow(at: locationInview)

if(gestureRecognizer.state == UIGestureRecognizerState.began)
{
if(tableview1.cellForRow(at: indexpath!)?.accessoryType ==
UITableViewCellAccessoryType.checkmark)
{
tableview1.cellForRow(at: indexpath!)?.accessoryType =
UITableViewCellAccessoryType.none
}
else{
tableview1.cellForRow(at: indexpath!)?.accessoryType =
UITableViewCellAccessoryType.checkmark
}
}
}

最佳答案

问题是单元格被重复使用,当您更新复选标记时,您更新的是单元格,而不是更新模型。因此,当单元格滚出 View 并重新使用该单元格时,您的 cellForRowAt 显然不会重置表格新行的复选标记。

同样,如果您将单元格滚动回 View ,cellForRowAt 无法知道是否应检查该单元格。你必须

  • 当您在单元格上检测到您的手势时,您必须更新您的模型以了解该行的单元格应该有一个检查;和

  • 您的 cellForRowAt 在配置单元格时必须查看此属性。

所以,首先要确保你的模型有一些值来指示它是否被选中/选中。在此示例中,我将使用“Item”,但您会使用更有意义的类型名称:

struct Item {
let name: String
var checked: Bool
}

然后您的 View Controller 可以在 cellForRowAt 中适本地填充单元格:

class ViewController: UITableViewController {

var items: [Item]!

override func viewDidLoad() {
super.viewDidLoad()

addItems()
}

/// Create a lot of sample data so I have enough for a scrolling view

private func addItems() {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
items = (0 ..< 1000).map { Item(name: formatter.string(from: NSNumber(value: $0))!, checked: false) }
}
}

extension ViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell
cell.delegate = self
cell.textLabel?.text = items[indexPath.row].name
cell.accessoryType = items[indexPath.row].checked ? .checkmark : .none
return cell
}
}

现在,我通常让单元格处理诸如识别手势之类的事情,并相应地通知 View Controller 。因此,创建一个 UITableViewCell 子类,并将其指定为 Storyboard上单元格原型(prototype)中的基类。但是单元格需要一些协议(protocol)来通知 View Controller 发生了长按:

protocol ItemCellDelegate: class {
func didLongPressCell(_ cell: UITableViewCell)
}

表格 View Controller 可以处理这个委托(delegate)方法,切换它的模型并相应地重新加载单元格:

extension ViewController: ItemCellDelegate {
func didLongPressCell(_ cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else { return }

items[indexPath.row].checked = !items[indexPath.row].checked
tableView.reloadRows(at: [indexPath], with: .fade)
}
}

然后,UITableViewCell 子类只需要一个长按手势识别器,并在识别到手势后通知 View Controller :

class ItemCell: UITableViewCell {

weak var delegate: CellDelegate?

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)

let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
addGestureRecognizer(longPress)
}

@IBAction func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
if gesture.state == .began {
delegate?.didLongPressCell(self)
}
}
}

顺便说一句,通过在单元格上设置手势,可以避免因“如果我长按不是单元格的东西会怎样”而导致的混淆。单元格是手势识别器的正确位置。

关于ios - 表格 View 单元格复选标记在滚动时更改位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46351448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com