iosswifttableviewcollectionviewtinder

Collection View cell in Table View Controller (like Tinder Message tab)


it is my first time to use Stack Overflow:) hope I can find the answers and give my knowledges.

I am currently making a chat app like Tinder or instagram style for studying Swift.

as you can see on Tinder, you can swipe horizontally matched users

https://i.sstatic.net/dFUcM.jpg

I want to build almost same design like that.

on my main.storyboard, it is like

TableViewController

   -collectionView

        -collectionViewCell
        -collectionViewFlowLayout

   -tableViewCell

        -contentView

like this.

collectionView cell is for matched users, and tableviewCells are for opened chatrooms.

I already finished making chatrooms.

but the collection view part never shows up. I tried to make Extension.swift file for this and typed like

 extension TableViewController {


   class RequestCVCell: UICollectionViewCell {

    @IBOutlet weak var MatchedAvatar: UIImageView!
    @IBOutlet weak var MatchedName: UILabel!

   override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
   MatchedAvatar.layer.cornerRadius = 30
   MatchedAvatar.clipsToBounds = true

    }


    let horizontalView = UIView(backgroundColor: .blue)

          }
 }

I thought about build a storyboard like

ViewController

   -collectionView

        -collectionViewCell
        -collectionViewFlowLayout

   -tableView

        -contentView

I really have no idea why it is not working. :( is there any way I can make like tinder?

thanks for reading and sorry for my English, lack of explanation.


Solution

  • I have created a sample project for you on github https://github.com/manojaher88/CollectionViewInTableView

    below is the code that might help you

    // MARK:- CellType
    enum CellType: Int, CaseIterable {
        case newMatches = 0
        case messages
    }
    
    // MARK:- NewMatch
    struct NewMatch {
        let name: String
        let imageName: String
    }
    
    // MARK:- ViewController
    class ViewController: UIViewController {
    
       enum Constants {
        static let nibName = "CollectionTableViewCell"
        static let reuseIdentifier = "CollectionTableViewCell"
    }
    
    @IBOutlet weak var tableView: UITableView!
    
    private var newMatches: [NewMatch] = []
    private var newMessages: [NewMatch] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
        createDataSource()
    }
    
    private func setupTableView() {
        tableView.delegate = self
        tableView.dataSource = self
        tableView.estimatedRowHeight = 100
        tableView.rowHeight = UITableView.automaticDimension
        let nibName = UINib(nibName: Constants.nibName, bundle: nil)
        tableView.register(nibName, forCellReuseIdentifier: Constants.reuseIdentifier)
    }
    
    private func createDataSource() {
        for i in 0...3 {
            let newMatch = NewMatch(name: "Matches \(i)", imageName: "image_1")
            newMatches.append(newMatch)
        }
    
        for i in 0...3 {
            let newMatch = NewMatch(name: "Messages \(i)", imageName: "image_1")
            newMessages.append(newMatch)
        }
    }
    }
    
    extension ViewController: UITableViewDelegate, UITableViewDataSource  {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return CellType.allCases.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.reuseIdentifier, for: indexPath) as? CollectionTableViewCell else {
            fatalError()
        }
        var dataSource: [NewMatch] = []
        let cellType = CellType(rawValue: indexPath.section)
        switch cellType {
        case .newMatches:   dataSource = newMatches
        case .messages:     dataSource = newMessages
        case .none: break
        }
        cell.update(newModels: dataSource)
    
        return cell
    }
    }
    
    class CollectionTableViewCell: UITableViewCell {
    
    enum Constants {
        static let nibName = "CollectionViewCell"
        static let reuseIdentifier = "CollectionViewCell"
    }
    
    @IBOutlet private weak var collectionView: UICollectionView!
    private var models: [NewMatch] = []
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        collectionView.delegate = self
        collectionView.dataSource = self
        let collectionViewCell = UINib(nibName: Constants.nibName, bundle: nil)
        collectionView.register(collectionViewCell, forCellWithReuseIdentifier: Constants.reuseIdentifier)
    }
    
    func update(newModels: [NewMatch]) {
        models.removeAll()
        models.append(contentsOf: newModels)
        collectionView.reloadData()
    }
    }
    
    extension CollectionTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return models.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.reuseIdentifier, for: indexPath) as? CollectionViewCell else {
            fatalError()
        }
    
        let model = models[indexPath.section]
        cell.userImage.image = UIImage(named: model.imageName)
        cell.userName.text = model.name
        return cell
    }
    }
    
    class CollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var userImage: UIImageView!
    @IBOutlet weak var userName: UILabel!
    
    override func prepareForReuse() {
        userImage.image = nil
    }
    }