代码方面发生了很多变化,因为我在过去一周左右一直在尝试对其进行调试 - 因此,我已将原始帖子移至 PDF。并且开始大部分新鲜:
简短概要:(基本未变)
- 一个
UITableViewController
(带有自定义类)包含UITableViewCell
(也是自定义类) - 表定义为只允许单选
- 初始“空”单元格(行 = 0)设置以在顶部提供一些填充 观点
- 希望能够切换单元格的选择(点击一次, 选中;再次点击它,取消选中)
- 我的代码(对我来说)看起来应该可以工作,但没有
- 因此,寻求一些指导/帮助等。
代码
下面是 [相关部分] 自定义 UITableViewController
代码(稍微重新格式化)
import UIKit
class ExistingLocationsViewController: UITableViewController {
var oldRow = -9999
var newRow = -1
var locationList: [LocationObject] = [
LocationObject(name: "name-1", address: "addr-1", phone: "phone-1", latitude: 40.0, longitude: -80.1),
LocationObject(name: "name-2", address: "addr=2", phone: "phone-2", latitude: 40.0, longitude: -80.1)
]
override func viewDidLoad() {
super.viewDidLoad()
// provides buffer space at the top so that the contents do not run into the top-margin (not needed if first cell is [intnetionally] blank)
self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
}
//... didReceiveMemoryWarning, numberOfSectionsInTableView, tableView(tableView: UITableView, numberOfRowsInSection section: Int)
// Did an override of willDisplayCell, but it seemed to neither hurt nor help my issue, so I removed it
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
let row = indexPath.row
let item = locationList[row]
cell.nameLabel.text = item.name
cell.locationLabel.text = item.address
print("cellForRowAtIndexPath: (row = \(row))(oldRow = \(oldRow))(newRow = \(newRow))[cell.selected = \(cell.selected)]")
//...attempt to set cell.accessoryType here neither hurt nor helped my issue, so I removed them
return cell
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
print("didDeselectRowAtIndexPath: (row = \(indexPath.row))(oldRow = \(oldRow))(newRow = \(newRow))[cell.selected = \(cell.selected)]")
print("didDeselectRowAtIndexPath => reloadRowsAtIndexPaths")
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
newRow = indexPath.row
print("didSelectRowAtIndexPath: (row = \(indexPath.row))(oldRow = \(oldRow))(newRow = \(newRow))[cell.selected = \(cell.selected)]")
if newRow == oldRow {
print("didSelectRowAtIndexPath => didDeselectRowAtIndexPath")
self.tableView(tableView, didDeselectRowAtIndexPath: indexPath)
cell.setSelected(false, animated: false) // before or after call to didDeselect but must be *here* and not *there*
oldRow = -1
}
else {
print("didSelectRowAtIndexPath => reloadRowsAtIndexPaths")
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
cell.setSelected(true, animated: false) // must be *after* call to reloadRowsAtIndexPaths
oldRow = indexPath.row
}
print("didSelectRowAtIndexPath: oldRow = '\(oldRow)'")
}
//... canEditRowAtIndexPath, commitEditingStyle
}
下面是自定义的UITableViewCell
代码(...)
import UIKit
class ExistingLocationTableViewCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
override func awakeFromNib() { super.awakeFromNib() }
// This is where the checkmark happens
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
let nm = self.nameLabel.text
let ad = self.locationLabel.text
if (nm?.isEmpty == false) { //avoids many calls to this function which don't represent an actual row
print("setSelected(\(selected), \(animated)): [name='\(nm)', location='\(ad)']:")
self.accessoryType = (selected == true) ? .Checkmark : .None
}
}
}
记录
下面是日志输出和我所看到的图像(还有一些额外的评论)
(1) 初始显示
cellForRowAtIndexPath: (row = 0)(oldRow = -9999)(newRow = -1)[cell.selected = false] setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: cellForRowAtIndexPath: (row = 1)(oldRow = -9999)(newRow = -1)[cell.selected = false] setSelected(false, false): [name='Optional("name-2")', location='Optional("addr-2")']:
(好:没有检查或突出显示)
(2) 单击 1:打开
setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: (row = 0)(oldRow = -9999)(newRow = 0)[cell.selected = true] didSelectRowAtIndexPath => reloadRowsAtIndexPaths cellForRowAtIndexPath: (row = 0)(oldRow = -9999)(newRow = 0)[cell.selected = false] setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: oldRow = '0'
(好:第 1 行已选中并突出显示)
(3) 单击 2:关闭
setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = true] didSelectRowAtIndexPath => didDeselectRowAtIndexPath didDeselectRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = true] didDeselectRowAtIndexPath => reloadRowsAtIndexPaths cellForRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = false] setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: oldRow = '-1' setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']:
(良好:第 1 行未选中且未突出显示)似乎发生了一些对
setSelected
的额外调用,不确定原因。(4) 单击 3:打开?
setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: (row = 0)(oldRow = -1)(newRow = 0)[cell.selected = true] didSelectRowAtIndexPath => reloadRowsAtIndexPaths setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: cellForRowAtIndexPath: (row = 0)(oldRow = -1)(newRow = 0)[cell.selected = false] setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: oldRow = '0'(错误:第 1 行仍未选中且未突出显示)
(无论您点击同一行多少次,图像都与上面完全相同)
(如果您点击第二行,它会经历同样的循环,一开始似乎有效,然后在第二次点击后不再显示为选中状态) 这应该看起来与第一次点击该行相同,但对
setSelected
有额外的调用,最终结果是错误的。(5) 单击 4:关闭?
setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(true, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = true] didSelectRowAtIndexPath => didDeselectRowAtIndexPath didDeselectRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = true] didDeselectRowAtIndexPath => reloadRowsAtIndexPaths cellForRowAtIndexPath: (row = 0)(oldRow = 0)(newRow = 0)[cell.selected = false] setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']: didSelectRowAtIndexPath: oldRow = '-1' setSelected(false, false): [name='Optional("name-1")', location='Optional("addr-1")']:(好的:第 1 行未选中且未突出显示,但可能不是出于正确的原因)
那么... 我再一次问 - 你看到我做错了什么了吗?我还应该做些什么来调试它吗?
最佳答案
您发布的内容很多,我很难理解。然而,一个潜在的问题很突出。我认为您想要复选标记附件来指示单元格已被选中,并且您有以下代码:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
let row = indexPath.row
let item = locationList[row]
cell.nameLabel.text = item.name
cell.locationLabel.text = item.address
cell.accessoryType = .None // initialize accessory icon?
return cell
}
然后在 didSelect
和 didDeselect
中,您正在更改附件。这不是 UITableView 的工作方式。它不记得状态——你必须自己做。在 didSelect
中,您应该存储 indexPath,然后重新加载表。这将通过再次调用 cellForRowAtIndexPath
重绘所有可见单元格。您的代码应决定是否使用类似于以下的代码显示复选标记:
cell.accessoryType = (indexPath == mySelectedIndexPath) ? .Checkmark : .None
mySelectedIndexPath
是您的存储状态。这应该在您的 viewController 中定义,而不是在单元格中 - 当您调用 dequeueReusableCellWithIdentifier
时,您可能会得到一个新的单元格,或者一个已被移出屏幕的现有初始化单元格。每次你得到一个,你必须假设它包含另一行的数据,并适本地设置一切。
关于ios - 如何切换 UITableViewContoller/UITableViewCell 中的选定行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39359111/