【问题标题】:duplicate data showing in UITableView after UIViewController being dismissedUIViewController 被解除后 UITableView 中显示的重复数据
【发布时间】:2021-10-31 23:47:28
【问题描述】:

问题: UITableview 即使在关闭数组后仍会填充重复数据

预期输出:

UITableview 根据数组中的itenary 项填充数据

实际输出:

当用户在 DiscoverVC 中选择第一个位置时,UITableView 会填充正确的输出量,但当用户选择另一个位置时,tableview 会附加用户先前选择的迭代数据。

总结:

我的项目中有 3VC,第一个 vc (DiscoverVC),将调用 api 在 UICollectionView 中填充数据,我实现 UICollectionView Delegate 以使用 segue 移动到另一个屏幕,在准备 segue 时我将数据从第一个 vc 传递到第二个 vc (ItenaryVC),在第二个 vc 里面我有 2 个视图。一个普通的vc,第二个是浮动面板(ItenaryFP)。当第二个 vc 加载时,它将基于已从第一个 vc 传递的 Location 对象进行 API 调用,并将数据通过 ItenaryVC 中的委托传递给作为浮动面板(ItenaryFP)的第三个 vc。

PS;我使用自定义单元格作为表格视图,并且已经尝试从 viewWillAppear 和 viewDidDissapear 中删除数组,但它仍然无法正常工作

GIF of how the issues occurs

这是我的代码摘要

DiscoverVC.swift

  class DiscoverVC : UIViewController {
    //MARK:- IBOutlets
    @IBOutlet weak var collectionView: UICollectionView!
    
    private var locationResult = [Location]()
    private var selectedAtRow : Int!
    
    //MARK:- Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        renderView()
        getLocations()
    }
    
    private func renderView() {
        collectionView.register(UINib(nibName: R.nib.discoverCell.name, bundle: nil), forCellWithReuseIdentifier: R.reuseIdentifier.discoverCell.identifier)
        collectionView.delegate = self
        collectionView.dataSource = self
    }
    
    private func getLocations(location : String = "locations") {
        
        NetworkManager.shared.getLocations(for: location) {  [weak self] location in
            
            switch location {
            
            case .success(let locations):
                self?.updateDiscoverUI(with: locations)
                
            case .failure(let error):
                print(error.rawValue)
            }
        }
    }
    
    private func updateDiscoverUI(with locations : [Location]) {
        
        DispatchQueue.main.async { [weak self] in
            self?.locationResult.append(contentsOf: locations)
            self?.collectionView.reloadData()
        }
    }
}

//MARK:- Delegate
extension DiscoverVC : UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        selectedAtRow = indexPath.row
        self.performSegue(withIdentifier: R.segue.discoverVC.goToDetails, sender: self)
        
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        guard let destinationVC = segue.destination as? ItenaryVC else { return}
        // Passing location object to ItenaryVC
        destinationVC.locationName = locationResult[selectedAtRow]
        destinationVC.imageURL = locationResult[selectedAtRow].image
      
        // Remove tab bar when push to other vc
        destinationVC.hidesBottomBarWhenPushed = true
        
    }
}

ItenaryVC.swift

   protocol ItenaryVCDelegate : AnyObject {
        func didSendItenaryData(_ itenaryVC : ItenaryVC, with itenary : [[Days]])
        func didSendLocationData(_ itenaryVC : ItenaryVC, with location : Location) 
    }
    
    class ItenaryVC: UIViewController {
        
        @IBOutlet weak var backgroundImage: UIImageView!
        
        var fpc : FloatingPanelController!
        var imageURL : URL?
        var locationName: Location?
    
        weak var delegate : ItenaryVCDelegate?
        
        //MARK:- Life Cycle
        override func viewDidLoad() {
            super.viewDidLoad()
            setupCard()
            setupView()
        }
        
        override func viewWillAppear(_ animated: Bool) {
            // Call API for data
            getItenaries(at: locationName!.itenaryName)
            print("ItenaryVC Appear")
        }
        override func viewWillDisappear(_ animated: Bool) {
            locationName = nil
        }
       
        
    }
    
    //MARK:- Network Request
    extension ItenaryVC {
        
        func getItenaries(at itenaries : String = "Melaka"){
            print("itenaries  : \(itenaries)")
            NetworkManager.shared.getItenaries(for: itenaries) { [weak self] itenary in
                switch itenary {
                
                case .success(let itenary):
                    // print(itenary)
                    DispatchQueue.main.async {
                        // Passing data to itenaryFP
                        self?.delegate?.didSendItenaryData(self! , with: itenary)
                    }
                    
                    print(itenaries.count)
                case .failure(let error):
                    print(error.rawValue)
                }
            }
        }
    }
    
    //MARK:- Private methods
    extension ItenaryVC {
        
        private func setupView() {
         
            
            backgroundImage.downloaded(from: imageURL!)
            backgroundImage.contentMode = .scaleAspectFill
            // Passing data to itenaryFP
            delegate?.didSendLocationData(self, with: locationName!)
        }
        
        private func setupCard() {
            guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFP else { return}
            // Initliase delegate to Floating Panel, create strong reference to Panel
            self.delegate = itenaryFlotingPanelVC
          
            fpc = FloatingPanelController()
            fpc.set(contentViewController: itenaryFlotingPanelVC)
            fpc.addPanel(toParent: self)
            fpc.delegate = self
            fpc.layout = self
            
        }
    }

ItenaryFP.swift

   class ItenaryFP: UIViewController{
    
    
    var itenaries = [[Days]]()
    var location : Location?
    
    //MARK:- : Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        print("ItrenaryFP viewDidLoad, itenaries : \(itenaries.count), location : \(location)")
        renderView()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        itenaries.removeAll()
        itenaryTableView.reloadData()

    }
    
    override func viewWillDisappear(_ animated: Bool) {
      
        DispatchQueue.main.async {
         
            self.itenaries.removeAll()
            print("ItenarFP dissapear, itenaries :\(self.itenaries.count), location : \(self.location)")
            self.location = nil
            self.itenaryTableView.reloadData()
        }

    }
    
   private func renderView() {
        itenaryTableView.register(UINib(nibName: R.nib.itenaryCell.name, bundle: nil), forCellReuseIdentifier: R.nib.itenaryCell.identifier)
        
        itenaryTableView.dataSource = self
        itenaryTableView.delegate = self
        
        locDescHC.constant = locDesc.contentSize.height
    }
}

//MARK:- Data source
extension ItenaryFP : UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        
        return itenaries.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return itenaries[section].count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        let cell : ItenaryCell = itenaryTableView.dequeueReusableCell(withIdentifier: R.nib.itenaryCell.identifier, for: indexPath) as! ItenaryCell
     
        let listOfItenaries = itenaries[indexPath.section][indexPath.row]
        
        cell.cellContent(for: listOfItenaries)
    
        return cell
    }
}



//MARK:- ItenaryVC Delegate
extension ItenaryFP : ItenaryVCDelegate {
    
    
    func didSendLocationData(_ itenaryVC: ItenaryVC, with location: Location) {

        DispatchQueue.main.async {
            self.locationLabel.text = location.locationName
            self.locDesc.text = location.description
            self.sloganLabel.text = location.slogan
        }
    }
    
    
    func didSendItenaryData(_ itenaryVC: ItenaryVC, with itenary: [[Days]]) {
        
        
        DispatchQueue.main.async {
            self.itenaries.append(contentsOf: itenary)
            self.itenaryTableView.reloadData()
            print("itenary \(self.itenaries.count)")
        }
    }
}

【问题讨论】:

  • 您需要设置一些断点,或添加一些print(...) 语句,您认为您的数组正在被清除。

标签: ios swift uitableview uicollectionview delegates


【解决方案1】:

用途:

self.itenaries = itenary 

代替:

self.itenaries.append(contentsOf: itenary)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多