关于代码已经改变了,因为我在过去一周左右一直试图调试这个 - 因此,我已将原始帖子移动到PDF并开始主要是新鲜的:
简短概要(基本不变)
UITableViewController
(包含自定义类)
UITableViewCell
的(也是自定义类)代码
以下是[自定义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")']:
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'
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")']:
setSelected
的一些额外调用似乎发生,不确定原因。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'( BAD:第1行仍未检查且未突出显示)
setSelected
来电并且最终结果是错误的。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")']:( OKAY:第1行未选中且未突出显示,但可能不是正确的原因)
所以... 再次,我问 - 你看到我做错了吗?我还应该做些什么来调试这个?
答案 0 :(得分: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
时,您可能会获得一个新单元格,或者现有已初始化的单元格已移出屏幕外。每次获得一个,你必须假设它包含另一行的数据,并适当地设置一切。
答案 1 :(得分:0)
这不是记录单元格中所选状态的好方法。 您可以在UITableViewController中记录选定的索引路径,在didSelectRowAtIndexPath方法中,您可以查看它是否已被选中,以及您希望这个索引路径。
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
cell.nameLabel.text = item.name
cell.locationLabel.text = item.address
if indexPath.row == selectedIndexPath {
//this cell is selected
cell.nameLabel.textColor = [UIColor redColor];
}
else {
//this cell is not selected
cell.nameLabel.textColor = [UIColor whiteColor];
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ExistingLocationTableViewCell
if indexPath.row == selectedIndexPath { // ignore the initial blank row
//do something like deselect
}
else {
//do something like select
}
}
答案 2 :(得分:0)
在另一个名单的人(Ole Begemann)的帮助下,我能够大大清理我的代码并使其完全正常工作。似乎没有按照要求工作的一件事是所选行保持突出显示而不是突出显示逐渐消失。
新代码涉及所有三个文件:
<强> LocationObject.swift 强>
添加了一个字段,用于跟踪每组数据的选择状态:
//将在其他地方使用的对象的简单类可能会被像UIMapKit这样的东西替换,但是现在......
进口基金会
class LocationObject {
var name: String!
var address: String!
var phone: String!
var latitude: Double!
var longitude: Double!
var selected: Bool! //<<== Added
init(name: String, address: String, phone: String, latitude: Double, longitude: Double, selected: Bool) { //<<== Added
self.name = name
self.address = address
self.phone = phone
self.latitude = latitude
self.longitude = longitude
self.selected = false //<<== Added
}
}
<强> ExistingLocationTableViewCell.swift 强>
不清楚是否甚至需要这个,因为我基本上删除了我之前做的自定义,但保留它以防万一它我需要在以后覆盖或扩展一些东西。
导入UIKit
class ExistingLocationTableViewCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
// Removed override of setSelected() - didn't seem to do anything
}
<强> ExistingLocationsViewController 强>
这是主要部分,涉及许多变化和清理。
导入UIKit
class ExistingLocationsViewController: UITableViewController {
var oldRow = -1 // Still used for aspect of state information (-1 instead of -9999)
//newRow removed, wasn't needed
var locationList: [LocationObject] = [ //<< Added 3rd row of data for more testing
LocationObject(name: "name-1", address: "addr-1", phone: "phone-1", latitude: 40.0, longitude: -80.1, selected: false),
LocationObject(name: "name-2", address: "addr-2", phone: "phone-2", latitude: 40.0, longitude: -80.1, selected: false),
LocationObject(name: "name-3", address: "addr-3", phone: "phone-3", latitude: 40.0, longitude: -80.1, selected: false)
]
上面没有任何重大变化。
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
numberOfRowsInSection
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
return cell
}
基本未更改,删除了调试语句
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! ExistingLocationTableViewCell
let row = indexPath.row
cell.accessoryType = .None
locationList[row].selected = false
oldRow = -1
}
以上内容发生了显着变化:
cellForRowAtIndexPath
代替dequeueReusableCellWithIdentifier
.None
&#39; selected
字段设置为&#39; false
&#39; oldRow
&#39;到&#39; -1
&#39;因为此功能仅在取消选择不同的以前选择的行时被调用(即:不是相同行的切换)
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! ExistingLocationTableViewCell
let row = indexPath.row
locationList[row].selected = !locationList[row].selected
cell.accessoryType = (locationList[row].selected == true) ? .Checkmark : .None
cell.highlighted = false
cell.setHighlighted(false, animated: true)
if oldRow == row { // TOGGLE
let oldIndexPath = NSIndexPath(forRow: oldRow, inSection: 0)
tableView.deselectRowAtIndexPath(oldIndexPath, animated: true)
oldRow = -1
}
else {
oldRow = row
}
}
}
以上内容发生了显着变化:
cellForRowAtIndexPath
代替dequeueReusableCellWithIdentifier
selected
字段设置为它正好相反(false
=&gt; true
|| true
=&gt; false
)cell.accessoryType
状态信息设置为引用当前选定的行(已选择)或&#39; oldRow
&#39; (未选)
上述更改的组合解决了我试图让行选择在辅助点击上切换的问题。希望这对于下一个尝试这样做的人来说会派上用场......