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.
Related
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 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
I have a tableview cell inside which i have added collectionview cell ( for horizontal scrolling).
Now i want to push to other navigation controller on pressing any cell of horizontal collectionview. How to do it ? Or how can i define delegate methods for cell press.
Code :
ViewController.swift :
class ViewController: UIViewController {
var categories = ["Action", "Drama", "Science Fiction", "Kids", "Horror"]
}
extension ViewController : UITableViewDelegate { }
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return categories[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return categories.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") as! CategoryRow
return cell
}
}
CategoryRow.swift
class CategoryRow : UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
}
extension CategoryRow : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! VideoCell
return cell
}
}
extension CategoryRow : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemsPerRow:CGFloat = 4
let hardCodedPadding:CGFloat = 5
let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
let itemHeight = collectionView.bounds.height - (2 * hardCodedPadding)
return CGSize(width: itemWidth, height: itemHeight)
}
}
VideoCell.swift
class VideoCell : UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
}
Here you will get the cell click at the delegate method didSelectItemAtIndexPath on CategoryRow class and from there you can fire a delegate to get call inside ViewController
ViewController.swift :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
cell.delegate = self
return cell
}
VideoCell.swift :
protocol CategoryRowDelegate:class {
func cellTapped()
}
CategoryRow.swift :
class CategoryRow : UITableViewCell {
weak var delegate:CategoryRowDelegate?
#IBOutlet weak var collectionView: UICollectionView!
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if delegate!= nil {
delegate?.cellTapped()
}
}
Add the delegate function inside ViewController
func cellTapped(){
//code for navigation
}
First create protocol for delegation from CategoryRow.swift like below code
protocol CollectionViewSelectionDelegate: class {
func didSelectedCollectionViewItem(selectedObject: AnyObject)
}
Now create delegate object on VideoCell.swift like below
weak var delegate:CollectionViewSelectionDelegate?
Change ViewController.swift code before return cell
cell?.delegate = self
Override method of delegate in ViewController.swift and call similar method from VideoCell.swift from UICollectionView Delegate method.
I think its better to use Notification in this case.
post a notification in didSelectItem of collection view
NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)
and add an observer in viewController viewDidLoad as follows
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(pushToNew(_:)), name: notificationIdentifier, object: nil)
in the new pushToNew function, perform your segue
func pushToNew(notification: Notification) {
// perform your segue here. Navigate to next view controller
}
Make a protocol
protocol collectionViewCellClicked{
func cellClicked()
}
Implement this protocol in main View Controller Your View Controller look like this
class ViewController: UITableViewController, collectionViewCellClicked{ func cellClicked(){ // Your Code }}
Your cellForRowAt delegate look like this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: <#T##String#>, for: <#T##IndexPath#>)
cell.delegate = self
return cell
}
In your Table View Cell Make a variable of type collectionViewCellClicked
var delegate: collectionViewCellClicked?
and in your didSelectItemAt delegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate.cellClicked()
}
I have a TableView with two kind of Cells, both are filled with a CollectionView. In the TableViewController I let them them display with a simple if Statement.
My TableViewController:
import UIKit
import RealmSwift
import Alamofire
import SwiftyJSON
let myGroupLive = DispatchGroup()
let myGroupCommunity = DispatchGroup()
class HomeVTwoTableViewController: UITableViewController {
var headers = ["Live", "Channel1", "ChannelTwo", "Channel3", "Channel4", "Channel5", "Channel6"]
override func viewDidLoad() {
super.viewDidLoad()
DataController().fetchSomeDate(mode: "get")
DataController().fetchSomeOtherData(mode: "get")
}
//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headers[section]
}
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
view.tintColor = UIColor.black
let header = view as! UITableViewHeaderFooterView
if section == 0 {
header.textLabel?.textColor = UIColor.black
view.tintColor = UIColor.white
}
else {
view.tintColor = UIColor.groupTableViewBackground
}
}
//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
return cell
}
else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
return cell
}
}
//Set custom cell height, has to match the CollectionView height
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return 225.0
}
else {
return 120.0
}
}
}
My TableViewCellSmall:
import UIKit
import RealmSwift
var communities: Results<Community>?
class HomeVTwoTableViewCellSmall: UITableViewCell{
#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 (communities?.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")
}
//Here I want my Sorting Statement to make unique content per collection view
//normal approach if no section is asked
let url : String = (communities?[indexPath.row].pictureUri)!
let name :String = (communities?[indexPath.row].communityName)!
cell.titleLbl.text = name
cell.imageView.downloadedFrom(link :"somelink")
return cell
}
//MARK: Delegate Methods
override func layoutSubviews() {
myGroupCommunity.notify(queue: DispatchQueue.main, execute: {
let realm = try! Realm()
communities = realm.objects(Community.self)
self.collectionView.dataSource = self
self.collectionView.delegate = self
})
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
do something
}
}
My Problem is now, I want the "Channel Cells" to fill with customized and different data, in the CollectionView. That means I need some sort of key to get the right data in the right cell. My approach would be to take the SectionHeader Title, but for some reasons I cant access it from the TableViewCellSmall. So I have all the data in all the Cells and cant sort them without my Key.
Thanks in Advance.
from what I understand you need to fill the collectionview of each cell with different contents and for this needs to identify the cell?
If so, I used the method below that helped me, you can try.
If in doubt let me know so I can help, I hope I have helped :)
//TableViewCell Add
var didCollectionViewCellSelect: ((Int) -> Void)?
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
//TabelView Add
class myClass: UITableViewController
{
var storedOffsets = [Int: CGFloat]()
override func viewDidLoad()
{
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
guard let tableViewCell = cell as? myTableViewCell else { return }
let secao = indexPath.section*1000 //Section
let linha = indexPath.row //Row
let posicao = secao+linha
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: posicao)
tableViewCell.collectionViewOffset = storedOffsets[posicao] ?? 0
}
override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
guard let tableViewCell = cell as? myTableViewCell else { return }
let secao = indexPath.section*1000 //Section
let linha = indexPath.row //Row
let posicao = secao+linha
storedOffsets[posicao] = tableViewCell.collectionViewOffset
}
}
//CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
let posicao = collectionView.tag
let secao = Int(collectionView.tag/1000) //Section
let linha = posicao-(secao*1000) //Row
var qtd = 0
if secao == 0 && arrStation.count > 0
{
qtd = arrStation.count
}
return qtd
}
I have made a CollectionView in a TableView for vertical and horizontal scrolling and customisable cells. This works so far. The problem is: I can't select an item of the CollectionView. I think the problem could be something with the delegate outlets but I could't find a solution.
I'm pretty new with Swift, so maybe I overlook something obvious.
My TableViewController:
import UIKit
class HomeVTwoTableViewController: UITableViewController {
var headers = ["Live", "Friends", "Last commented"]
#IBAction func cancelBtnPressed(_ sender: UIBarButtonItem) {
self.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headers[section]
}
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
view.tintColor = UIColor.black
let header = view as! UITableViewHeaderFooterView
if section == 0 {
header.textLabel?.textColor = UIColor.black
view.tintColor = UIColor.white
}
else {
view.tintColor = UIColor.groupTableViewBackground
}
}
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 {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
return cell
}
else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
return cell
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return 225.0
}
else {
return 120.0
}
}
}
My TableViewCell with the CollectionView:
import UIKit
class HomeVTwoTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
fileprivate var images = [UIImage]()
{
didSet
{
self.collectionView.reloadData()
}
}
func setup(for images: [UIImage])
{
self.images = images
}
override func layoutSubviews() {
collectionView.dataSource = self
}
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return communityName.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return communityName.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("didSelect")
selectedCommunity = communityId[indexPath.row]
let home = HomeViewController()
home.showCommunityDetail()
}
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")
}
//cell.imageView.image = image
cell.titleLbl.text = communityName[indexPath.row]
cell.imageView.downloadedFrom(link :"deleted because privat")
return cell
}
}
My CollectionViewCell:
import UIKit
class HomeVTwoCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var titleLbl: UILabel!
}
You need to set delegate and dataSource like this
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
collectionView.dataSource = self
collectionView.delegate = self
}
I think you missed this line. Just add, it will work fine collectionView.delegate = self
You have not confirm delegate of collection view.
override func layoutSubviews() {
collectionView.dataSource = self
collectionView.delegate = self
}