UITableView inside UICollectionView -> [error] unexpectedly found nil while unwrapping tableView - ios

I have a UITableView inside each cell of a UICollectionView.
I referenced the table view to a FeedCell class, which is a class for each cell in the collection view. However, I got an error saying
fatal error: unexpectedly found nil while unwrapping an Optional value
when trying to access the tableView object in the FeedCell class. I triple checked that I referenced the table view from the storyboard correctly, so I'm assuming there's something else that's causing it to be nil, but I'm not sure what it is. Does anyone have a clue about how to fix this?
This is my VC where both the collection view and the table view lies.
class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isTranslucent = false
collectionView.register(FeedCell.self, forCellWithReuseIdentifier: "FeedCell")
}
// for feedcell and its collection view
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FeedCell", for: indexPath) as! FeedCell
cell.backgroundColor = backgrounds[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let collectionViewCell = cell as? FeedCell else { return }
collectionViewCell.setTableViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
// conform to tableview protocol for hometable
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return images[tableView.tag].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath)
cell.imageView?.image = images[tableView.tag][indexPath.item]
return cell
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: animated)
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
super.viewWillDisappear(animated)
}
}
And here's a cell of the collection view where I reference the table view.
class FeedCell: BaseCollectionViewCell{
#IBOutlet weak var tableView: UITableView!
override func setupViews() {
super.setupViews()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
}
extension FeedCell {
func setTableViewDataSourceDelegate
<D: UITableViewDataSource & UITableViewDelegate>
(dataSourceDelegate: D, forRow row: Int) {
# ERROR!
tableView.delegate = dataSourceDelegate
tableView.dataSource = dataSourceDelegate
tableView.tag = row
tableView.reloadData()
}
}

On this line:
(dataSourceDelegate: D, forRow row: Int)
You cast it as the variable: D
Use this instead:
tableView.dataSource = D
tableView.delegate = D

Related

tvOS: Unable to scroll through UICollectionView items when it is implemented like this: UICollectionView inside UITableView

I have implemented this:
By following this tutorial.
Here's the problem:
I am unable to scroll through the collection items.
I think this has something to do with the fact that the project I followed is for iOS and my project is for tvOS.
I've found a somewhat similar question. An answer linked to this GitHub Repo whose implementation doesn't seem that different from mine.
Here's the relevant code:
ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell =
tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as? TableViewCell
else {
fatalError("Unable to create explore table view cell")}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
}
tableViewCell.swift
class TableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
collectionView.delegate = self
collectionView.dataSource = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
extension TableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// For some reason he chose the measures of collectionViewCell and substracted 2
return CGSize(width: 139, height: 64)
}
// Highlight the current cell
// This doesn't work
func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
if let pindex = context.previouslyFocusedIndexPath, let cell = collectionView.cellForItem(at: pindex) {
cell.contentView.layer.borderWidth = 0.0
cell.contentView.layer.shadowRadius = 0.0
cell.contentView.layer.shadowOpacity = 0.0
}
if let index = context.nextFocusedIndexPath, let cell = collectionView.cellForItem(at: index) {
cell.contentView.layer.borderWidth = 8.0
cell.contentView.layer.borderColor = UIColor.orange.cgColor
cell.contentView.layer.shadowColor = UIColor.orange.cgColor
cell.contentView.layer.shadowRadius = 10.0
cell.contentView.layer.shadowOpacity = 0.9
cell.contentView.layer.shadowOffset = CGSize(width: 0, height: 0)
collectionView.scrollToItem(at: index, at: [.centeredHorizontally, .centeredVertically], animated: true)
}
}
}
In a separate project, I have implemented a collectionView independently. I.e: It was not embedded inside of a tableView. And it works just fine.
I copied the code from that project that highlights the selected cell and added it to the tableViewCell.swift but it had no impact at all.
So my question is:
Why am I unable to select a cell and/or scroll through the
collectionView?
Found the answer here:
By denying the focus of the table cell, the Focus engine will
automatically find the next focusable view on the screen. And in your
case, that is the collection view’s cell.
func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool {
return false
}

Nested UICollectionView returning the same values for each section - Swift

I have a UICollectionView nested inside of a UITableViewCell. The collectionview inside of each tableviewcell section should return different data according to the section. Here is my code:
ViewController.swift
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
var categoryKeys: [String]?
let network = MediaNetworking()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// fetch data
network.fetchMedia()
tableView.delegate = self
tableView.dataSource = self
print("hello world")
}
func numberOfSections(in tableView: UITableView) -> Int {
self.categoryKeys = network.categoryKeys
return self.categoryKeys!.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SectionTableViewCell
cell.theArray = network.sharedArray
cell.accessArray = network.accessArray
cell.backgroundColor = .purple
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
self.categoryKeys = network.categoryKeys
return self.categoryKeys?[section]
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
}
SectionTableViewCell.swift
class SectionTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var categoryKeys: [String]?
var theArray: [String: [Entity]]?
var accessArray: [Entity]?
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
collectionView.delegate = self
collectionView.dataSource = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return accessArray!.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MediaCollectionViewCell
cell.artistLabel.text = accessArray![indexPath.row].name
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "SectionHeaderView", for: indexPath) as! SectionHeaderView
if indexPath.section < categoryKeys!.count {
let category = categoryKeys![indexPath.section]
sectionHeader.categoryLabel.text = category
}
return sectionHeader
}
return UICollectionReusableView()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 400, height: 300)
}
}
Right now all the collectionview cells are returning the same values. Any ideas on what I might be missing?..
Did you try to call collectionView.reloadData() after changing the data arrays?
cell.theArray = network.sharedArray
cell.accessArray = network.accessArray
cell. collectionView.reloadData()

I am Trying to Create an Expandable Table View With Child Element Having a UICollection View

I am Trying to Create a Table View which is
Expandable
It's Childview has a UICollectionView
UICollectionView is Dynamically rendered using API
onTouch Event of UICollectionView Item should be taken care of
Tried couple of samples didn't work
import UIKit
extension String{
func print(){
Swift.print(self)
}
func log(){
Swift.print(self)
}
}
class CustomVCViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , UICollectionViewDataSource, UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ccell", for: indexPath) as! CustomCollectionViewCell
cell.backgroundColor = UIColor.blue
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
"Selection of Collection View item at \(indexPath.row)".print()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
"Selection of Table View item at \(indexPath.row)".print()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! CustomTableViewCell
cell.innerCollectionView.dataSource = self
cell.innerCollectionView.delegate = self
cell.backgroundColor = UIColor.red
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
}
}
This is for the table view cell
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var innerCollectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
According to my understanding you want the tableviewcell to be expandable as collection view so Im adding the code for it , the thing is collectionview is not invalidating its first internsic content size accordingly
/// This CollectionView class is used to invalidate collectionview's default implementation of inrinsic content size
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return collectionViewLayout.collectionViewContentSize
}
}
SO add this class to your collectionview and provide flowlayout to your collectionviewcells. also!!! return UITableViewAutomaticDimension on heightforRowAt of tableview.

UICollectionView inside of UITableViewCell

I am attempting to set a CollectionView inside of a TableViewCell. I have read through a hand full of stack questions, tuts, and videos and so far I have what appears to be the correct method but my collection view is still not loading into my table view cell.
Code:
import UIKit
class TheaterCell: UITableViewCell {
#IBOutlet var theaterName: UILabel!
#IBOutlet var theaterLocation: UILabel!
#IBOutlet var showtimesCollection: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
showtimesCollection.delegate = self
showtimesCollection.dataSource = self
showtimesCollection.reloadData()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension TheaterCell: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = showtimesCollection.dequeueReusableCell(withReuseIdentifier: "timeCell", for: indexPath) as! TimeCell
cell.time.text = "1:00"
return cell
}
}
The Tableview loads from the ViewController and is displaying its cells and elements but the collection view is not loading within the cell.
This is working for me, I think the problems comes from the way you register your cell
class YourCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
registerCell()
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
func registerCell() {
collectionView.register(TimeCell.self, forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! TimeCell
cell.time.text = "1:00"
return cell
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
What I do, I use storyboard and setting the delegates & datasource from Storyboard by dragging into the classes.
a) Set TableView's delegates & datasource to ViewController
b) Set CollectionView's delegates & datasource to TableViewCell(TheaterCell)
ViewController Code:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
extension ViewController:UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let theaterCell:TheaterCell = tableView.dequeueReusableCell(withIdentifier: "TheaterCell", for: indexPath) as! TheaterCell
theaterCell.reloadCollectionView()
return theaterCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
}
TheaterCell Code:
class TheaterCell: UITableViewCell {
#IBOutlet var showtimesCollection: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
}
func reloadCollectionView() -> Void {
self.showtimesCollection.reloadData()
}
}
extension TheaterCell: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = showtimesCollection.dequeueReusableCell(withReuseIdentifier: "timeCell", for: indexPath) as! TimeCell
cell.time.text = "1:00"
return cell
}
}
TimeCell Code:
class TimeCell: UICollectionViewCell {
#IBOutlet var time: UILabel!
}
Here is the output:
NOTE: IF YOU ARE NOT USING STORYBOARDS AND YOU MAKE COLLECTIONVIEW OR TABLE FROM CODE ONLY, THEN YOU HAVE REGISTER YOURS CELL AS:
A) TheaterCell must be registered into ViewController class
B) TimeCell must be registered into TheaterCell class

Segue in a UICollectionView embedded in a UITableviewCell, Swift

I have made a UICollectionView inside a UITableViewCell and it works pretty Fine. My only Problem is, that I can't perform a Segue on didSelectItemAt Method to another ViewController.
I know I have to perform it from the TableViewController,I made a segue on the Storyboard and I tried multiple possibilities but for some reasons it doesn't work.
Here my TableviewController:
import UIKit
import RealmSwift
import SwiftyJSON
class HomeVTwoTableViewController: UITableViewController {
let realm = try! Realm()
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.separatorStyle = .none
}
//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
cell.update()
return cell
} else {
return UITableViewCell()
}
}
// This on of my tries to perform a segue
func liveCellSelected() {
performSegue(withIdentifier: "showChat", sender: nil)
}
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
import RealmSwift
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old image
cell.imageView.image = UIImage(named: "No Image")
cell.titleLbl.text = nil
//set url and Picture
url = (liveCommunities?[indexPath.row].pictureId)!
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
cell.imageView.downloadedFrom(link :"someSecretUrl")
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
}
}
I found another question with a similar theme, but couldn't implement a delegate Protocol without creating problems with the already existing delegates.
Maybe it`s an obvious mistake but I can't see it.
Thanks in advance.
You're instantiating a new instacne of your home controller with this:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
}
what you should do is to make it via a delegate, or you move your collectionview delegate to the main controller
protocol CellCollectionViewDelegate: class{
func didselect()
}
and you implement the delegate in cell and your home controller
May be you can create a variable to handle this. You can do optional also.
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
#IBOutlet weak var collectionView: UICollectionView!
var didSelectAction: () -> Void // add your action here
Here you can call to this function
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
HomeVTwoTableViewController().liveCellSelected()
didSelectAction() // Invoque your action
}
//On the cell creator, add the navigation or logic when you want to tap the cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
cell.update()
cell.didSelectAction = {
// add here your navigation
}
return cell
} else {
return UITableViewCell()
}
}
Ok as it seems there are two Solutions to this Problem.
One is via a Variable and one via a delegate. As I know the delegate one is more common.
Solution 1 with Variable:
Here my TableviewController:
import UIKit
class TableViewController: UITableViewController {
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
//Fill function, insert Navigation
cell.didSelectAction = {
self.performSegue(withIdentifier: "testSegue", sender: nil)
}
return cell
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
//Instantiate function
var didSelectAction: () -> Void = {}
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old text
cell.titleLbl.text = nil
cell.senderLbl.text = nil
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
// Invoque your action
didSelectAction()
}
}
Solution 2 with Delegate and Protocol:
Here my TableviewController:
import UIKit
class TableViewController: UITableViewController {
let headers = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
//Add delegate
cell.delegate = self
return cell
}
//Add Extension with Navigation
extension HomeVTwoTableViewController: CellCollectionViewDelegate {
func didSelect() {
performSegue(withIdentifier: "showChat", sender: nil)
}
}
And here my TableViewCell with the embedded CollectionView:
import UIKit
//Create a delegate protocol
protocol CellCollectionViewDelegate: class{
func didSelect()
}
class HomeVTwoTableViewCell: UITableViewCell{
var liveCommunities: Results<Community>?
//Add a delegate property
weak var delegate: CellCollectionViewDelegate?
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
}
}
//Adopt and implement the Delegate Protocol
extension HomeVTwoTableViewCell:
UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return(liveCommunities?.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
{
fatalError("Cell has wrong type")
}
//removes the old text
cell.titleLbl.text = nil
cell.senderLbl.text = nil
let name : String = (liveCommunities?[indexPath.row].communityName)!
let channelName : String = (liveCommunities?[indexPath.row].channelName)!
cell.titleLbl.text = name
cell.senderLbl.text = channelName
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
//call delegate method
delegate?.didSelect()
}
}
I tried to sum up the Solutions from
Abdoelrhman Mohamed and Alexkater and write it out in detail.
Tell me if something is wrong or left out.

Resources