【发布时间】: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 中删除数组,但它仍然无法正常工作
这是我的代码摘要
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