Jan Swoboda
Jan Swoboda

Reputation: 172

Passing TableViewCell to a new TableView (at the top) Swift

What I want to do: I have a feed (TableView( and once the user taps on a Post (TableViewCell), he should see a new Page (TableView) with the Post he tapped on first (the same TableViewCell) on top and a couple of comments below.

My Problem: I dont get how to "clone" that TableViewCell.

Here two pictures for a better understanding:

The Feed with the Post I want to clone

This is how it should look: The Post in the first section and cloned from the Cell the user clicked on

Some complications: I have multiple post types in the main feed, so the code would have to differentiate between them to see which cell type to use to display the content.

My code:

Main Feed

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0{
            return mixed.count
        }
        else if section == 1{
            return phots.count
        }
        else{
            return texttt.count
        }

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.section == 0{
            let cell = tableView.dequeueReusableCell(withIdentifier: mixedTableViewCell.identifier, for: indexPath) as! mixedTableViewCell
            cell.configure(with: self.mixed[indexPath.row])
            return cell
        }
        else if indexPath.section == 1{
            let cell = tableView.dequeueReusableCell(withIdentifier: popularTableViewCell.identifier, for: indexPath) as! popularTableViewCell
            cell.configure(with: self.phots[indexPath.row])
            return cell
        }
        else{
            let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
            cell.configure(with: self.texttt[indexPath.row])
            return cell
        }

    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "commentsVC")
        vc.modalPresentationStyle = .fullScreen

        self.navigationController?.pushViewController(vc, animated: true)
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return UITableView.automaticDimension
    }

My second ViewController

class CommentsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var table: UITableView!

    var texty = [TextComment]()

    override func viewDidLoad() {
        super.viewDidLoad()

        table.register(popularTableViewCell.nib(), forCellReuseIdentifier: popularTableViewCell.identifier)
        table.register(featuredTableViewCell.nib(), forCellReuseIdentifier: featuredTableViewCell.identifier)
        table.register(textTableViewCell.nib(), forCellReuseIdentifier: textTableViewCell.identifier)
        table.register(mixedTableViewCell.nib(), forCellReuseIdentifier: mixedTableViewCell.identifier)
        table.register(textComTableViewCell.nib(), forCellReuseIdentifier: textComTableViewCell.identifier)


        table.delegate = self
        table.dataSource = self


    }



    func numberOfSections(in tableView: UITableView) -> Int {
        2
    }


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0{
            return 1
        }
        else{
            return 15
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0{
            let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
            return cell
        }
        else{
            let cell = tableView.dequeueReusableCell(withIdentifier: textComTableViewCell.identifier, for: indexPath) as! textComTableViewCell
            return cell
        }
    }


    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.section == 0{
//            self.table.estimatedRowHeight = 250
//            self.table.rowHeight = UITableView.automaticDimension
//            return UITableView.automaticDimension
            return 300
        }
        else{
//            self.table.estimatedRowHeight = 150
//            self.table.rowHeight = UITableView.automaticDimension
//            return UITableView.automaticDimension
            return 150
        }
    }

Note Right now the it isnt working at all, how I want it. I just have these "mock" posts as space-fillers in there.

Any help or ideas would be greatly appreciated!

My structs

struct PhotoPost {
    let numberOfComments: Int
    let username: String
    let timestampName: String
    let userImageName: String
    let postImageName: String
    let postID: String
}

struct TextPost {
    let numberOfComments: Int
    let username: String
    let timestampName: String
    let userImageName: String
    let textName: String
    let postID: String
}

struct MixedPhoto {
    let numberOfComments: Int
    let username: String
    let timestampName: String
    let userImageName: String
    let textName: String
    let postImageName: String
    let postID: String
}

Here my errors: enter image description here

enter image description here

enter image description here

Upvotes: 0

Views: 49

Answers (1)

Aleksandr Medvedev
Aleksandr Medvedev

Reputation: 8968

Each instance of UITableView has its own pool of cells, for this reason it would not be correct to "steal" an instance of the cell from one UITableView and put it into another. Also, as far as i can see you already have a convenient way to feed your cells with data, and dequeue corresponding types. Thus the only thing left here is to pass the required data from MainFeed under your tableView(_: didSelectRowAt:) function, something like that:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let vc = storyboard.instantiateViewController(withIdentifier: "commentsVC") as? CommentsViewController else {
       return
    }
    switch indexPath.section {
        case 0:
            vc.mixedData = mixed[indexPath.row]
        case 1:
            vc.photoData = photos[indexPath.row]
        default:
            vc.textData = texttt[indexPath.row]
    }
    vc.modalPresentationStyle = .fullScreen

    navigationController?.pushViewController(vc, animated: true)
}

And then, under the CommentsViewController's tableView(_:, cellForRowAt:) function, implement pretty much the same stuff you did in MainFeed:

var mixedData: MixedPhoto?
var photoData: PhotoPost?
var textData: TextPost?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        let cell: UITableViewCell
        switch (mixedData, photoData, textData) {
        case (.some(let value), _, _):
            cell = tableView.dequeueReusableCell(withIdentifier: mixedTableViewCell.identifier, for: indexPath) as! mixedTableViewCell
            cell.configure(with: value)
        case (_, .some(let value), _):
            cell = tableView.dequeueReusableCell(withIdentifier: popularTableViewCell.identifier, for: indexPath) as! popularTableViewCell
            cell.configure(with: value)
        case (_, _, .some(let value)):
            cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
            cell.configure(with: value)
        default:
            fatalError("The data is not set")
        }
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: textComTableViewCell.identifier, for: indexPath) as! textComTableViewCell
        return cell
    }
}

Also I should say that it's a good idea to implement a common protocol for your data types, so you actually can define a single non-optional variable in the CommentsViewController instead of three optionals.

Upvotes: 2

Related Questions