UITableView:reloadRows(at :)需要两次命中才能更新表并每次滚动 [英] UITableView: reloadRows(at:) takes two hits for table to be updated and scroll every time

查看:147
本文介绍了UITableView:reloadRows(at :)需要两次命中才能更新表并每次滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表视图(控制器: MetricsViewController ),该视图从CoreData数据库进行更新。我使用了根据需要定制的原型单元( MetricsViewCell )。它包含一个分段控件,一个UIView(metricsChart,用于显示图表-animationCircle)和一些UILabel。

I have a table view (controller: MetricsViewController) which gets updated from a CoreData database. I have used prototype cells (MetricsViewCell) which I have customized for my needs. It contains a segmented control, a UIView (metricsChart, which is used to display a chart - animatedCircle), and some UILabels.

MetricsViewCell

class MetricsViewCell: UITableViewCell {
    
    var delegate: SelectSegmentedControl?
    var animatedCircle: AnimatedCircle?
    
    @IBOutlet weak var percentageCorrect: UILabel!
    @IBOutlet weak var totalPlay: UILabel!
    
    @IBOutlet weak var metricsChart: UIView! {
        didSet {
            animatedCircle = AnimatedCircle(frame: metricsChart.bounds)
        }
    }
    @IBOutlet weak var recommendationLabel: UILabel!
    
    @IBOutlet weak var objectType: UISegmentedControl!
    
    @IBAction func displayObjectType(_ sender: UISegmentedControl) {
        delegate?.tapped(cell: self)
        
    }
}

protocol SelectSegmentedControl {
    func tapped(cell: MetricsViewCell)
}

MetricsViewController

class MetricsViewController: FetchedResultsTableViewController, SelectSegmentedControl {

func tapped(cell: MetricsViewCell) {
    if let indexPath = tableView.indexPath(for: cell) {
        tableView.reloadRows(at: [indexPath], with: .none)
    }
}

var container: NSPersistentContainer? = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer { didSet { updateUI() } }

private var fetchedResultsController: NSFetchedResultsController<Object>?

private func updateUI() {
    if let context = container?.viewContext {
        let request: NSFetchRequest<Object> = Object.fetchRequest()
        request.sortDescriptors = []
        fetchedResultsController = NSFetchedResultsController<Object>(
            fetchRequest: request,
            managedObjectContext: context,
            sectionNameKeyPath: "game.gameIndex",
            cacheName: nil)
        try? fetchedResultsController?.performFetch()
        tableView.reloadData()
    }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Object Cell", for: indexPath)
    if let object = fetchedResultsController?.object(at: indexPath) {
        
        if let objectCell = cell as? MetricsViewCell {
            objectCell.delegate = self
            
            let request: NSFetchRequest<Object> = Object.fetchRequest()
            ...
            ...

            }
        }
    }
    return cell
}

当用户在某个节的分段控件中选择一个分段时,MetricsViewController应该在该特定行中重新加载数据。 (有两个部分,每个部分一行)。因此,我在MetricsViewCell中定义了一个协议,以通知控制器我的用户操作。

When a user selects one of the segments in a certain section's segmented control, MetricsViewController should reload the data in that particular row. (There are two sections with one row each). Hence, I've defined a protocol in MetricsViewCell to inform inform my controller on user action.

正在使用 FetchedResultsTableViewController 更新数据-它基本上充当CoreData和TableView之间的委托。一切都很好,这意味着我可以在TableView中获取正确的数据。

Data is being updated using FetchedResultsTableViewController - which basically acts as a delegate between CoreData and TableView. Everything is fine with that, meaning I am getting the correct data into my TableView.

有两个问题:


  1. 我必须点按两次细分控件的细分,以重新加载点击了细分控件的行中的数据。

  1. I have to tap segmented control's segment twice to reload the data in the row where segmented control was tapped.

表格滚动每次从分段控制中选择一个分段后,都可以上下备份。

The table scrolls back up and then down every time a segment from segmented control is selected.

非常感谢您的帮助。我在开发过程中遇到了很多问题,现在都依靠这个社区,并且已经很感激了:)

Help would be very much appreciated. I've depended on this community for a lot of issues I've faced during the development and am thankful already :)

例如,在动物识别部分,我必须点击中级两次以重新加载该行(如果您仔细观察,我第一次点击中级时,它会被选中一秒钟的时间,然后又回到基本或首先选择的任何段。第二次是当我点击中级,转到中级)。另外,该表可以上下滚动,这是我不希望的。

For example, in Animal Recognition section, I have to hit "Intermediate" two times for its row to be reloaded (If you look closely, the first time I hit Intermediate, it gets selected for a fraction of second, then it goes back to "Basic" or whatever segment was selected first. Second time when I hit intermediate, it goes to Intermediate). Plus, the table scroll up and down, which I don't want.

编辑:为我对CoreData和持久性容器的使用添加了更多上下文。

Edit: Added more context around my usage of CoreData and persistent container.

推荐答案

您的 UISegmentedControl 正在重用[UITableView的默认行为]。

Your UISegmentedControl are reusing [Default behaviour of UITableView].

为避免这种情况,请保留 dictionary 来获取和存储值。

To avoid that, keep dictionary for getting and storing values.

另一件事,在 UIViewController <中尝试将出口连接作为操作用于 UISegmentedControl / code>本身,而不是您的 UITableViewCell

Another thing, try outlet connection as Action for UISegmentedControl in UIViewController itself, instead of your UITableViewCell

以下代码将不会在您重新加载tableview时使用点击 UISegmentedControl 。您可以避免,代表也可以打电话。

The below code will not reload your tableview when you tap UISegmentedControl . You can avoid, delegates call too.

以下代码是 UISegmentedControl 的基本演示。根据您的需要进行自定义。

Below codes are basic demo for UISegmentedControl. Do customise as per your need.

var segmentDict = [Int : Int]()


override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0...29 // number of rows count
    {
        segmentDict[i] = 0 //DEFAULT SELECTED SEGMENTS
    }

}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SOTableViewCell

    cell.mySegment.selectedSegmentIndex = segmentDict[indexPath.row]!

    cell.selectionStyle = .none
    return cell
}

@IBAction func mySegmentAcn(_ sender: UISegmentedControl) {

    let cellPosition = sender.convert(CGPoint.zero, to: tblVw)
    let indPath = tblVw.indexPathForRow(at: cellPosition)

    segmentDict[(indPath?.row)!] = sender.selectedSegmentIndex


    print("Sender.tag     ", indPath)

}

这篇关于UITableView:reloadRows(at :)需要两次命中才能更新表并每次滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆