【问题标题】:TableView Index out of range issueTableView 索引超出范围问题
【发布时间】:2021-07-11 15:07:35
【问题描述】:

我的视图控制器打开一个目录,计算其中的文件类型并将结果存储在文件类型和计数的字典 [String:Int] 中。我有一个显示这个的 TableView。

当我第一次打开一个目录时,ViewController 会在 FileTypeTableview 中正确显示信息。如果我尝试打开另一个目录,则执行到该行:

let dialogButton = dialog.runModal()

然后立即跳转到我的 TableView 函数中的一行并在此处抛出一个超出范围的索引:

val = types[row]

Types 是 [String] 并显示 0 个元素,row 是 Int 并显示 0。 我对在 dialog.runModal() 函数调用中发生这种情况感到困惑。

以下是获取目录并显示 TableView 的函数。 我对 Swift 和 MacOS 编程非常陌生,如果有任何见解,我将不胜感激。

@IBAction func getFolder(_ sender: Any) {
    
    let dialog = NSOpenPanel()
    dialog.canChooseDirectories = true
    dialog.canChooseFiles = false
    
    allFiles = []
    fileTypesDict.removeAll()
    
    let dialogButton = dialog.runModal()
    
    if let theURL = dialog.url {
    theDirectory = theURL.path
    allFilesAsPaths = getAllFiles2(atDirectoryPath: theURL.path)
    allFilesAsPaths.sort()
        
    }
    
    fileCountLabel.stringValue = String(allFilesAsPaths.count)
    
    mainTableView2.reloadData()
    fileTypeTableView.reloadData()
}



func numberOfRows(in tableView: NSTableView) -> Int {
            
    var numberOfRows : Int = 0
    
    if tableView == mainTableView2 {
        print("number of rows for mainTableView2")
        numberOfRows = allFilesAsPaths.count
    } else if tableView == fileTypeTableView {
        print("number of rows for fileTypeTableView")
        numberOfRows = fileTypesDict.count
    } else if tableView == exifTableView {
        numberOfRows = exifData.count
        print("exifData.count = \(exifData.count)")
        print("number of rows for exifTableview \(numberOfRows)")
    }
    return numberOfRows
}

func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
    
    var val : String = ""
    
    if tableView == mainTableView2 {
    val = allFilesAsPaths[row]
    }
    if tableView == exifTableView {
        if tableColumn?.identifier.rawValue == "tag" {
            let tagArray : [String] = Array(exifData.keys)
            val = tagArray[row]
        } else if tableColumn?.identifier.rawValue == "value" {
            let valueArray : [String] = Array(exifData.values)
            val = valueArray[row]
        }
    }
    
    if tableView == fileTypeTableView {

    let types : [String] = Array(fileTypesDict.keys)
    let counts : [Int] = Array(fileTypesDict.values)

    if tableColumn?.identifier.rawValue == "type" {
            val = types[row]
        } else {
            val = String(counts[row])
        }
    }
    return val
}

【问题讨论】:

  • 在没有可用数据时尝试检查您是否正在制作单元格。简而言之:当 indexpath 超过你的 arrayList
  • 可能提供更多代码或更准确地描述您想要实现的目标(表格和项目的性质),因为这就像您在一个类中处理三个不同的表格。

标签: swift macos nstableview


【解决方案1】:

我认为你应该尝试删除

allFiles = []
fileTypesDict.removeAll()

并在对话框验证后立即设置所有数组。因为看起来显示对话框会触发表格的更新,但此时,您的对象并未同步,因为您在之前和之后做了一些工作。

顺便说一句,如果你做单独的表类比处理if tableView == ... {} 会更清楚。你冒着让你的代码逐渐变得密不可分的风险。我已经去过那里了;)

【讨论】:

  • 谢谢你——你是对的。似乎这可能触发了 TableView 的重新加载。一旦移动它似乎按预期工作。关于在一个类中处理多个 TableView,这将是我计划发布的另一个问题。我想知道应该如何处理属于同一窗口的多个 TableView。
  • 酷 :) 这取决于您显示的项目类型。例如,如果您的三个表显示文件名,那么您将创建一个 TableView 类,该类包含一个带有 name 属性的 FileItem 数组。在此数组的didSet 上,您重新加载表。分发物品的所有逻辑都在外面。您创建三个文件对象数组,然后映射到文件项数组并将其分配给每个项数组。这种方法有一个优点,即使你弄乱了文件数组,与表关联的项目也不会被修改。不确定我在这里是否清楚..
  • 相反,如果您的三个表处理不同的对象/列名等,请创建三个不同的表和/或表数据源。职责分离在软件设计中绝不是一个糟糕的选择。
  • 我确实理解您所说的从概念上分解显示非常不同数据的表格视图的处理。我想我只是还不明白如何创建一个新类来充当数据源和 tableview(s) 的委托——然后建立连接。我可以创建一个自定义视图控制器子类并使其符合 NSTableView 协议,但我不明白如何将情节提要出口连接到 tableview。 (我意识到这是非常基本的东西,我会搜索一些相关的教程......只是还没有找到它们。:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多