【问题标题】:How to programmatically select a row in UITableView in Swift如何以编程方式在 Swift 的 UITableView 中选择一行
【发布时间】:2015-09-23 17:26:02
【问题描述】:

我需要使用 Swift 1.2 以编程方式在 UITableView 中选择一行。

这是简单的代码:

var index = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)
self.tableView(self.tableView, didSelectRowAtIndexPath: index)

上面给了我以下错误:

无法使用类型为“(NSIndexPath!,动画:Bool,scrollPosition:UITableViewScrollPosition)”的参数列表调用“selectRowAtIndexPath”

我的 Swift 1.2 代码有什么问题?

我的 UItableView 已在我试图调用上面代码的 UIViewController 中的 IB 中创建。 当我将代码放在 UITableViewController 中时,编译器不会给出任何错误。 我需要在容器中嵌入 UITableViewController 还是有其他方法?

【问题讨论】:

  • 不,第二行编译得很好。
  • 您是否在视图控制器中定义了tableView 属性(并将其连接到IB 中的表视图)?这可能是stackoverflow.com/questions/30733126/… 的副本吗?
  • @MartinR 我确实使用 IBOutlet weak var menuTable: UITableView 在我的 VC 中定义并连接了一个 tableView 属性!但是我没有控制这个 tableView 的 UITableViewController。我不能用 TVC 替换我的 VC,因为我需要 iPad 项目中的其他元素。我的 VC 中有一个主容器,它对 tableView 中的选择做出反应。我试图在我的 VC 中创建一个容器,然后在其中嵌入一个 TVC。这会正确显示菜单项,但是我在更改主容器显示的内容时遇到了问题(基于菜单中的选择)。具体来说,它有一个问题:
  • @Mikee:如果您的表格视图属性称为“menuTable”,那么您应该将其称为self. menuTable.selectRowAtIndexPath(...),下一条语句类似。
  • @MartinR 太棒了!如此简单 - 非常感谢您的帮助!您是否愿意将您的评论作为答案,以便我可以为您提供正确的答案?

标签: ios swift uitableview


【解决方案1】:

在使用数据加载表格视图后使用以下代码:

let rowToSelect:NSIndexPath = NSIndexPath(forRow: 0, inSection: 0);  //slecting 0th row with 0th section
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None);

现在,您必须使用以下代码手动调用 didSelectRowAtIndexPath: 委托方法:

self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect); //Manually trigger the row to select

谢谢。

【讨论】:

  • @ShaileshChandavar Pankaj 是对的......你为什么不能手动调用 didSelectRowAtIndexPath ?假设最初你必须选择一个特定的行,你怎么能做到这一点?
  • “调用此方法不会导致委托接收 tableView:willSelectRowAtIndexPath: 或 tableView:didSelectRowAtIndexPath: 消息,也不会向观察者发送 UITableViewSelectionDidChangeNotification 通知。” docs for selectRowAtIndexPath
  • 但是这如何解释问题中报告的编译器错误
  • 我的 UItableView 已经在我试图调用上面代码的 UIViewController 中的 IB 中创建。当我将代码放在 UITableViewController 中时,编译器不会给出任何错误。我需要在容器中嵌入 UITableViewController 还是有其他方法?
【解决方案2】:

声明

self.tableView.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)

假定tableView 是视图控制器的一个属性,已连接 到情节提要中的表格视图。例如,UITableViewController 已经有这个 财产。

在您的情况下,视图控制器不是表视图控制器 而是UIViewController 的子类。它还有一个插座是 连接到表视图,但它没有被调用 tableViewmenuTable。那你当然得打电话

self.menuTable.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)

选择该表格视图的一行。

奇怪的错误信息是由以下事实引起的 self.tableView 也可以被编译器理解为 “咖喱函数”(比较 http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/)。

【讨论】:

  • 斯威夫特 3:self.tableView.selectRow(at: index, animated: true, scrollPosition: .middle)
  • @MartinR 当我们在做 UI 选择时,不需要 selectRowAtIndexPath(indexDispatchQueue.main.async 中吗?
【解决方案3】:

使用 Swift 2.x,如Pankaj purohit answers 所述,正确的方法是:

func tapRowAtIndex(index:Int) {
        let rowToSelect:NSIndexPath = NSIndexPath(forRow: index, inSection: 0)
        self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None)
        self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect)
}

请记住,例如,如果您从外部类调用此方法,您不知道 tableView 何时完成加载,那么有什么可能性?如何解决这个问题? :

第一步:创建一个类布尔变量

var automatingTap: Bool = false

第二步:检查表何时完成加载并启动“结束操作”方法:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) 
{
    let lastRowIndex = tableView.numberOfRowsInSection(0)
    if indexPath.row == lastRowIndex - 1 {
       endOperations()
    }
}

func endOperations() 
{
   print("finished loading")
   if automatingTap {
        tapRowAtIndex(0)
        automatingTap = false
   }
}

第三步:从另一个类调用我的tableView类

例如:

override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
    if segue!.identifier == "DetailsTableView" {
        let viewController:ViewController = segue!.destinationViewController as ViewController
        viewController.automatingTap = true
    }
}

【讨论】:

    【解决方案4】:

    Swift 3Swift 5 解决方案

    选择一行

    let indexPath = IndexPath(row: 0, section: 0)
    myTableView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
    myTableView.delegate?.tableView!(myTableView, didSelectRowAt: indexPath)
    

    取消选择行

    let deselectIndexPath = IndexPath(row: 7, section: 0)
    myTableView.deselectRow(at: deselectIndexPath, animated: true)
    myTableView.delegate?.tableView!(myTableView, didDeselectRowAt: indexPath)
    

    【讨论】:

    • 感谢您的帮助 - 我不知道您必须直接调用委托方法!为了避免可能的崩溃,我将! 换成? in myTableView.delegate?.tableView!
    【解决方案5】:

    斯威夫特 3.x

    如果你想在'cell-creation'中这样做,你可以这样做

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = TableViewCell()
        let item = items[indexPath.row]
    
        cell.textLabel?.text    = item.title
    
        if (item.checked) {
            tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        }
    
        return cell
    }
    

    【讨论】:

      【解决方案6】:

      Swift 4.2

      选择一个或多个行

      let ndx:IndexSet = [1]
      // or:  let ndx:IndexSet = [1, 2, 3]; // etc
      tableview?.selectRowIndexes(ndx, byExtendingSelection: false);
      

      取消选择单行

      tableview?.deselectRow(current)
      

      请注意,如果您已实现 (func tableViewSelectionDidChange(...)),则会由上述触发。

      另请参阅 Charlton Provatas 在https://stackoverflow.com/a/48696458/352920 的回答,了解 NSTableView 的扩展,它提供了一个简单的

      tableview?.selectRow(at:) 
      

      【讨论】:

        【解决方案7】:

        可重用函数,可验证表大小

        斯威夫特 4 和 5

        这个可重用的函数起作用并验证表的大小。

        func selectRow(tableView: UITableView, position: Int) {
            let sizeTable = tableView.numberOfRows(inSection: 0)
            guard position >= 0 && position < sizeTable else { return }
            let indexPath = IndexPath(row: position, section: 0)
            tableView.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
        }
        

        你可以这样使用它

        selectRow(tableView: myTableView, position: pos)
        

        或者你可以实现这个扩展:

        extension UITableView {
            func selectRow(row: Int, section: Int = 0) {
                let sizeTable = self.numberOfRows(inSection: section)
                guard row >= 0 && row < sizeTable else { return }
                let indexPath = IndexPath(row: row, section: section)
                self.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
            }
        }
        

        你可以这样使用它:

        mytableView.selectRow(row: pos, section: 0)
        

        mytableView.selectRow(row: pos)
        

        【讨论】:

          猜你喜欢
          • 2012-11-28
          • 1970-01-01
          • 1970-01-01
          • 2017-03-06
          • 1970-01-01
          • 2011-09-10
          • 1970-01-01
          • 1970-01-01
          • 2012-02-16
          相关资源
          最近更新 更多