TableView中的CollectionView显示false Data swift

时间:2017-06-26 10:19:17

标签: ios swift uitableview swift3 uicollectionview

我试图将CollectionViewTableView结合起来,所以除了一个问题外,一切都有效,我无法解决这个问题。

我必须在CollectionViews中加载一些数据,这些数据使用CollectionView所在的TableViewCell的标题进行排序。出于某种原因,每次我启动应用程序时,前三个TableViewCells都是相同的。如果我垂直滚动一点,它们会更改为正确的数据。 但也可能发生这种情况,即使用它有时会显示与TableViewCell另一个TableViewCell上相同的数据,如果我稍微滚动一下,问题就会解决。

我认为问题是可重复使用的细胞,但我自己找不到错误。我尝试插入colletionView.reloadData()并在重复使用之前将单元格设置为nil,遗憾的是这不起作用。

我的TableViewController

import UIKit
import RealmSwift
import Alamofire
import SwiftyJSON

let myGroupLive = DispatchGroup()
let myGroupCommunity = DispatchGroup()
var channelTitle=""

class HomeVTwoTableViewController: UITableViewController {


var headers = ["LIVE","Channel1", "Channel2", "Channel3", "Channel4", "Channel5", "Channel6"]

override func viewDidLoad() {
    super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
     self.navigationController?.navigationBar.isTranslucent = false
   DataController().fetchDataLive(mode: "get")
   DataController().fetchDataCommunity(mode: "get")
}

//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return headers[section]
}

//MARK: DataSource Methods
override func numberOfSections(in tableView: UITableView) -> Int {
    return headers.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

//Choosing the responsible PrototypCell for the Sections
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
        print("TableViewreloadMain")
        cell.collectionView.reloadData()
        return cell
    }
    else if indexPath.section >= 1 {
        // getting header Titel for reuse in cell
        channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
        // anti Duplicate protection
        cell.collectionView.reloadData()

        return cell
    }

    else {
        channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
        // anti Duplicate protection
        cell.collectionView.reloadData()

        return cell
    }
}
}
}

我的TableViewCell与`CollectionView

import UIKit
import RealmSwift

var communities: Results<Community>?

class HomeVTwoTableViewCellSmall: UITableViewCell{

//serves as a translator from ChannelName to the ChannelId
var channelOverview: [String:String] = ["Channel1": "399", "Channel2": "401", "Channel3": "360", "Channel4": "322", "Channel5": "385", "Channel6": "4"]
//Initiaize the CellChannel Container
var cellChannel: Results<Community>!

//Initialize the translated ChannelId
var channelId: String = ""

@IBOutlet weak var collectionView: UICollectionView!

 }

 extension HomeVTwoTableViewCellSmall: UICollectionViewDataSource,UICollectionViewDelegate {

//MARK: Datasource Methods
func numberOfSections(in collectionView: UICollectionView) -> Int
{
    return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    return (cellChannel.count)
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellSmall", for: indexPath) as? HomeVTwoCollectionViewCellSmall else
    {
        fatalError("Cell has wrong type")
    }
    //removes the old image and Titel
    cell.imageView.image = nil
    cell.titleLbl.text = nil
    //inserting the channel specific data
    let url : String = (cellChannel[indexPath.row].pictureId)
    let name :String = (cellChannel[indexPath.row].communityName)
    cell.titleLbl.text = name
    cell.imageView.downloadedFrom(link :"link")
    return cell
}


//MARK: Delegate Methods

override func layoutSubviews() {
    myGroupCommunity.notify(queue: DispatchQueue.main, execute: {

        let realm = try! Realm()
        //Getting the ChannelId from Dictionary
        self.channelId = self.channelOverview[channelTitle]!

        //load data from Realm into variables
        self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ")

        self.collectionView.dataSource = self
        self.collectionView.delegate   = self
        print("collectionView layout Subviews")
        self.collectionView.reloadData()
    })

}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    selectedCommunity = (cellChannel[indexPath.row].communityId)
    let home = HomeViewController()
    home.showCommunityDetail()
}
}

提前致谢。

1 个答案:

答案 0 :(得分:0)

tl; dr使channelTitle成为您单元格上的变量,而不是全局变量。另外,在prepareForReuse

上清除它和其他单元格变量

我可能会在这里弄错,但是你创建它们后是否在单元格上设置了channelTitle?正如我所看到的,在viewController中,您可以根据标题创建单元格,并为每个单元格设置TableViewController的{​​{1}}作为给定部分的标题。

如果是这种情况,那么在您致电channelTitle之前,TableViewCell实际上没有收到任何有关它应该加载的信息。

一般情况下,我还建议您在reloadData()中实施prepareForReuse,因为它会让您有机会清理任何过时的数据。可能你会想要设置HomeVTwoTableViewCellSmallcellChannel之类的东西来清空该方法中的字符串或channelId,所以当重复使用该单元时,旧数据会一直存在。

另外,我只是重新阅读了您拥有的单元格代码,看起来您正在nil中进行一些关键的初始单元设置。该方法可能会被大量调用,但实际上只需要调用一次(对于它所做的大部分工作)。试试这个:

  • 使用单元格上的重用标识符覆盖init
  • 在该init中,添加layoutSubviewsself.collectionView.dataSource = self
  • self.collectionView.delegate = self
  • 上添加didSet
  • 在viewController中设置channelTitle

所以代码看起来像:

channelTitle

这样,您只需在使用新频道更新单元格时重新加载数据,而不是单元格视图的每个布局。

对不起......还有一个补充。我不知道你的var channelTitle: String = "" { didSet { self.channelId = self.channelOverview[channelTitle]! self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ") self.collectionView.reloadData() } } 实际上是如何通过的。在我看来,你将channelTitle用作全局变量而不是本地变量。不要那样做!在实现上述代码之前,从当前的位置删除channelTitle。您将看到一些错误,因为您在ViewController中设置它并在单元格中访问它。你想要的是从ViewController设置单元格channelTitle(如上所述)。这也解释了为什么你在所有三个单元格中看到相同的数据。基本上你只设置了一个channelTitle,所有三个单元格都在寻找那个全局值来获取它们的数据。

希望有所帮助!

(另外,您应该可以删除channelTitle方法中的else if块,因为其后面的cellForRowAtIndexPath块包含相同的代码。您还可以删除viewDidLoad ,因为它没有做任何事情,你应该通常看看你是否可以摆脱任何else因为它们不安全。使用!?guard代替