tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview

Posted

技术标签:

【中文标题】tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview【英文标题】:tableView.reloadData() and DispatchQueue not working to reload tableview in different view controller 【发布时间】:2021-05-31 16:41:27 【问题描述】:

我有两个视图控制器,一个带有表格视图(第一个 VC),第二个可以通过导航栏中的按钮导航到。第二个视图控制器应该能够将一个表格视图单元格添加到第一个视图控制器的表格视图中。

第一个视图控制器:

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 
let tableView = UITableView()
var data = ["mars", "earth", "jupiter", "venus", "saturn"]

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    view.addSubview(tableView)
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    tableView.delegate = self
    tableView.dataSource = self

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    tableView.frame = view.bounds

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return data.count

    
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = data[indexPath.row]
    return cell

第二个视图控制器:

import UIKit

class SecondViewController: UIViewController 

@IBOutlet var imageView: UIImageView!
@IBOutlet var button: UIButton!
@IBOutlet var addPostButton: UIButton!

override func viewDidLoad() 
    super.viewDidLoad()
    title = "Second Screen"
    
    
    // Do any additional setup after loading the view.


@IBAction func didTapButton()
    let picker = UIImagePickerController()
    picker.sourceType = .photoLibrary
    picker.allowsEditing = true
    picker.delegate = self
    present(picker, animated: true)


@IBAction func didTapAddPostButton()
    let FVC = FirstViewController()
    FVC.data.append("New data added!")
    DispatchQueue.main.async
    FVC.tableView.beginUpdates()
    FVC.tableView.performBatchUpdates(
            FVC.tableView.insertRows(at: [IndexPath(row: FVC.data.count - 1,
                                                     section: 0)],
                                      with: .automatic)
        , completion: nil)
    FVC.tableView.endUpdates()
    
    print("TapAddPostButton pressed")
    print(FVC.data)




extension SecondViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate 
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) 
        picker.dismiss(animated: true, completion: nil)
    
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) 
        
        picker.dismiss(animated: true, completion: nil)
        
        guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else 
            return
        
        imageView.image = image
    

应该发生什么:按下第二个视图控制器中的按钮后,应该添加一个新的表格单元格,然后重新加载表格视图。

实际情况: tableview 没有被重新加载。当我滑回第一个视图控制器时,tableview 和以前一样,并且没有重新加载和更新新单元格。

图片:

This is the first view controller

This is the second view controller

【问题讨论】:

你能添加声明问题的图片吗?? 我已经添加了图片@Menaim 与问题无关,但beginUpdates/endUpdatesperformBatchUpdates 对于单个插入操作都毫无意义。除此之外,这两种形式都是同义词。 查看我更新的答案,我认为它会解决问题 【参考方案1】:

当你这样做时:

let FVC = FirstViewController()

...您正在创建一个新的、不相关的 FirstViewController 实例。这行不通。查看delegates + protocols 或closures (或显示您在哪里展示SecondViewController 的代码,我会更新我的答案)。

【讨论】:

我已经更新了我的帖子以包含我展示 SecondViewController 的代码 它在“第二个视图控制器”下的主帖中 @Hilardy 啊我的意思是你展示 SecondViewController 的地方。最有可能在didSelectIndexAt.【参考方案2】:

如果你需要实现它,最好使用协议能够以正确的方式链接这两个viewControllers

在您需要的任何地方创建协议:

protocol PassingProtocol 
func saveData(withText myText: String) 

然后在FirstViewController:

extension FirstViewController: PassingProtocol 
     func saveData(withText myText: String) 
       data.append(myText)
       DispatchQueue.main.async 
           self.tableView.reloadData()
        
   

NewEntryBarbutton的行动中:

let myVC = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as! SecondViewController
    myVC.textDelegate = self
    self.navigationController?.pushViewController(myVC, animated: true)
    

SecondViewController

var textDelegate: PassingProtocol!

那么在didTapAddPostButton的动作中:

textDelegate.saveData(withText: "New data added!")

如果您需要使用插座,请按照以下步骤操作:

FirstViewController.Swift:

import UIKit

class FirstViewController: UIViewController 

    var data = ["mars", "earth", "jupiter", "venus", "saturn"]

    @IBOutlet weak var tableViewOutlet: UITableView!
    override func viewDidLoad() 
        super.viewDidLoad()




    
    @IBAction func newEntryAction(_ sender: Any) 
        let myVC = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as! SecondViewController
            myVC.textDelegate = self
            self.navigationController?.pushViewController(myVC, animated: true)
            
        
    
    


extension FirstViewController : UITableViewDelegate, UITableViewDataSource 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        data.count
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableViewOutlet.dequeueReusableCell(withIdentifier: "MyCell") as! MyCell
        cell.lblData.text = data[indexPath.row]
        return cell
    
    
    

extension FirstViewController: PassingProtocol 
     func saveData(withText myText: String) 
       data.append(myText)
       DispatchQueue.main.async 
           self.tableViewOutlet.reloadData()
        
   


SecondViewController.Swift

import UIKit

class SecondViewController: UIViewController 

    @IBOutlet weak var textFieldData: UITextField!
    var textDelegate: PassingProtocol!

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    
    

    @IBAction func addEntryButtonAction(_ sender: Any) 
        textDelegate.saveData(withText: textFieldData.text!)

    


PassingProtocol.Swift

import Foundation

    protocol PassingProtocol 
    func saveData(withText myText: String)
    

MyCell.Swift

import UIKit

class MyCell: UITableViewCell 

    @IBOutlet weak var lblData: UILabel!


效果很好,我自己试过了,效果很好

【讨论】:

刚刚完成实施。我收到错误Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file SecondViewController.swift, line 34 第 34 行是 textDelegate.saveData() 我现在修改一下 检查新解决方案@Hilardy 我在 SecondViewController 中收到错误 Cannot find type 'PassingProtocol' in scope 创建它,我已经在解决方案中提到了这个并且已经在解决方案中创建了它【参考方案3】:

从画廊拍照后。将委托函数传递给 FirstVC。 FirstVC - 函数包含数据和数据计数。在调度队列方法中加载 Tableview。

【讨论】:

以上是关于tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview的主要内容,如果未能解决你的问题,请参考以下文章

[tableView reloadData] 和 runloop

tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview

Swift:tableView.reloadData() 表中没有数据

tableView reloadData 和 deselectRowAtIndexPath

每次视图出现时 tableView.reloadData()

iOS TableView reloadData刷新列表cell乱跳tableview闪动的问题。