How to show view controller on selecting row cell

2019-08-25 21:27发布

问题:

I have the Main View Controller which has a collection view with its collection view cells each initialized as a tableView to serve multiple rows inside of that collection view cell. If you're getting confused, below is the snapshot of the current state.

The problem is when I try to tap a tableView row cell to open another view controller, It fails and a selected state of table view cell is shown.

Here is the snapshot.

//HomeCollectionViewCell.swift
class HomeCollectionViewCell: UICollectionViewCell {
override func layoutSubviews() {
    super.layoutSubviews()
    setUpCellView()
}
func setUpCellView() {
    let frame = CGRect(x:20, y:20, width: bounds.width - 40, height: 600)
    let cell = CellView(frame: frame)
    contentView.addSubview(cell)
  }
}

//CellView.swift
class CellView: UITableView {
    let quoteCell = "QuoteCell"
    let newsCell = "NewsCell"
    let articleCell = "ArticleCell"
    override init(frame: CGRect, style: UITableViewStyle) {
        super.init(frame: frame, style: .grouped)
        self.layer.cornerRadius = 15
        self.backgroundColor = .white
        self.dataSource = self
        self.delegate = self
        self.register(QuoteTableViewCell.self, forCellReuseIdentifier: quoteCell)
        self.register(NewsTableViewCell.self, forCellReuseIdentifier: newsCell)
        self.register(ArticleTableViewCell.self, forCellReuseIdentifier: articleCell)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
extension CellView: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    switch indexPath.section {
        case 0: return 35
        case 1: return 140
        case 2: return 100
        case 3: return 140
        default: return 0
    }
  }
}
extension CellView: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
    return categories.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return categories[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
        case 0: let cell = tableView.dequeueReusableCell(withIdentifier: dateCell)
                cell?.textLabel?.text = "Today"
                cell?.textLabel?.font = UIFont.systemFont(ofSize: 30, weight: UIFont.Weight.heavy)

        return cell!
        case 1: let cell = tableView.dequeueReusableCell(withIdentifier: quoteCell) as! QuoteTableViewCell
        return cell
        case 2: let cell = tableView.dequeueReusableCell(withIdentifier: newsCell) as! NewsTableViewCell
        return cell
        case 3: let cell = tableView.dequeueReusableCell(withIdentifier: articleCell) as! ArticleTableViewCell
        return cell
        default: let cell = tableView.dequeueReusableCell(withIdentifier: commonCell)
        cell?.textLabel?.text = "LOL"
        return cell!
    }
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    switch indexPath.section {
    case 0: print("Date Selected")
    case 1: print("Quote Selected")
    case 2: print("News Selected")
    case 3: let homeViewController = HomeViewController()
            let articleDetailViewController = ArticleDetailViewController()
//homeViewController.show(articleDetailViewController, sender: homeViewController)//homeViewController.navigationController?.pushViewController(articleDetailViewController, animated: true)
    homeViewController.present(articleDetailViewController, animated: true, completion: nil)
            print("Article selected")
    default: print("LOL")
    }
  }   
}

//HomeViewController.swift

class HomeViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    setupNavBar()
    view.addSubview(collectionView)
    setUpConstraints()
    configure(collectionView: collectionView)
}
func setUpConstraints() {
    _ = collectionView.anchor(view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, topConstant: 10, leftConstant: 10, bottomConstant: 10, rightConstant: 10, widthConstant: 0, heightConstant: 0)
    collectionView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}

lazy var collectionView : UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
    let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    cv.translatesAutoresizingMaskIntoConstraints = false
    cv.alwaysBounceVertical = true
    cv.clipsToBounds = true
    cv.showsHorizontalScrollIndicator = false
    cv.showsVerticalScrollIndicator = false
    cv.backgroundColor = .clear
    cv.isHidden = false
    return cv
}()
}
private let reuseIdentifier = "Cell"
extension HomeViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
internal func configure(collectionView: UICollectionView) {
    collectionView.register(HomeCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! HomeCollectionViewCell
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.bounds.width, height: 600)
}
}

Please tell where I'm doing wrong or What approach should I use?

Note- No use of storyboards/IB. Done things programmatically only.

回答1:

Give identifiers("HomeViewController" and "ArticleDetailViewController") to view controllers and try below code in didSelectRow().

case 3:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let sourceViewController = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController
let destinationViewController = storyboard.instantiateViewController(withIdentifier: "ArticleDetailViewController") as? ArticleDetailViewController
let navigator: UINavigationController = sourceViewController as! UINavigationController                                                                                                                                                       
navigator.pushViewController(destinationViewController!, animated: true)


回答2:

From what have you done, I want to point out that its not a good idea to present UIViewController from UView. You must write some custom delegates which will get fired once someone taps on those cells in the custom CellView class. Those delegates must be implemented in the view controller that contains the tableview. From the UIViewController you must write the code to present the new viewcontrollers.