首页 > 解决方案 > 表格单元格中的活动指示器视图

问题描述

我有一张桌子,我想把它做成这样,当我点击一个单元格时,活动指示器会围绕它旋转,而不是在一个难以理解的地方

在此处输入图像描述

它看起来像这样。在代码中,我有 MainViewController 模块和 Presenter 模块,它们确定何时启动活动指示器。我有一个出口

@IBOutlet weak var activity: UIActivityIndicatorView! = UIActivityIndicatorView(style: .gray)

我在视图控制器中有两个函数可以启动动画和停止

func startActivity() {
   activity.startAnimating()
}


func stopActivity() {
   activity.stopAnimating()
}

有一个函数可以处理对单元格的点击

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   tableView.deselectRow(at: indexPath, animated: true)
   output.callFromThePresenter(array: array[indexPath.row])

}

此功能在演示器中实现。

func callFromThePresenter(array: String) {

  let userInteractiveQueue = DispatchQueue.global(qos: .userInteractive)

  async {
    DispatchQueue.main.async  {
        self.view.startActivity()
    }
    userInteractiveQueue.async {
         self.interactor.functionFromInteractor(data: array)
    }
  }
}

正如我所假设的,在视图控制器中,当您单击一个单元格时,callFromThePresenter() 函数将起作用,并且 Interactor 中的动画功能和数据传输功能将在其中启动,只要 Interactor 完成此功能,它将数据返回给Presenter,在回调函数内部,我将运行stopActivity()函数。它一直有效,直到我决定设置定位

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   tableView.deselectRow(at: indexPath, animated: true)
   output.callFromThePresenter(array: array[indexPath.row])
   let cell = tableView.cellForRow(at: indexPath)
   cell?.accessoryView = self.activity
}

一旦我添加了这两行

let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryView = self.activity

我打破了一切,好像我启动了一样,我点击表格单元格,轮子在需要的地方转动,一切正常,但是在收到结果后,我再次戳了某个单元格,整个程序挂起,我没有不知道是什么原因。同时,函数计算出我能理解多少,因为到了控制台,函数启动并得到了一些结果,但是整个 UI 卡住了,我什么也做不了

标签: swiftuitableviewuiactivityindicatorview

解决方案


简单的例子:

  • 在 Interface Builder 中Style,将表格视图单元格的 设置为custom
  • 将标签和活动指示器拖到单元格中,并根据需要设置适当的约束。
  • 选择活动指示器,按⌘⌥4(Attributes Inspector) 并选中Hides When Stopped
  • 创建自定义类,UITableViewCell项目中的子类

    class TitleCell: UITableViewCell {
    
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet weak var activity: UIActivityIndicatorView!
    
        var isRunning : Bool = false {
            didSet {
                isRunning ? activity.startAnimating() : activity.stopAnimating()
            }
        }
    }
    
  • 在 Interface Builder 中设置原型单元的类,TitleCell并将标签和指示器连接到IBOutlets

  • 创建一个至少具有一个title和一个isRunning属性的数据模型。

    struct Model {
        let title: String
        var isRunning : Bool
    }
    
  • 声明一个数据源数组

    var items = [Model]()
    
  • cellForRow更新 UI 元素(将标识符替换为您的真实标识符)

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TitleCell
        let item = items[indexPath.row]
        cell.titleLabel!.text = item.title
        cell.isRunning = item.isRunning
        return cell
    }
    
  • 启动和停止指示器工具didSelectRow

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        items[indexPath.row].isRunning.toggle()
        tableView.reloadRows(at: [indexPath], with: .none)
    }
    

要更改指标的状态,请始终使用在模型中设置isRunning的模式并重新加载行。


推荐阅读