Images In a Collection View - swift

I am coding in Swift 3.2, and inside of a TableView Controller have a TableView (scrolling vertically), and each row of the table holds a CollectionView (scrolling horizontally).
I am not sure if it is acceptable coding practice, but I made my ViewController class inherit UITableViewController and UICollectionViewDelegate and UICollectionViewDataSource.
For now, I have a hard coded array of image names and would like three images to scroll horizontally in each collection view, with each row having distinct images. However, as of now each row shows the same three images ("11.png", "12.png", "13.png"), and I was wondering how to fix this.
Below is my ViewController class.
//for the tableView
let event = generateRandomData()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return event.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
}
//for the collectionView
var images: [String] = [
"11.png", "12.png", "13.png",
"21.png", "22.png", "23.png",
"31.png", "32.png", "33.png",
"41.png", "42.png", "43.png",
"51.png", "52.png", "53.png",
"61.png", "62.png", "63.png",
"71.png", "72.png", "73.png",
"81.png", "82.png", "83.png",
"91.png", "92.png", "93.png",
"101.png", "102.png", "103.png",
]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
collectionView.isPagingEnabled = true; //makes the horizontal scrolling have no bounce and relatively have a better snap
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath as IndexPath) as! CollectionViewCell
let myCellImage = UIImage(named: images[indexPath.row])
myCell.eventImage.image = myCellImage
return myCell
}
I am an amateur coder, so any help is greatly appreciated!

I am sure this problem already have an answer somewhere, but since I can't find that I'll just give one here.
Your mistake is here:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
/...
let myCellImage = UIImage(named: images[indexPath.row]) //<< indexPath.row will return 0,1 and 2 for each of your collection view
/...
}
Each collection view in your table view does not communicate amongst themselves to form a larger collective view. Since all of the are provided the int of 3 for numberOfItemsInSection and their numberOfSections defaulted to 1(you did not set any), each of them will request for item at indexpath (0,0), (0,1) and (0,2) when trying to populate their data.
Your hardcoded array however, is an array with 30 items. So each collection view when requesting for cellForItemAt will only get 0,1 and 2 for images[indexPath.row]. Also you should use indexPath.item for collection view, indexPath.row is for table views, it may or may not work if used wrongly.
Solution
You can just set the tag property of the collection view to mark it's row:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
/...
//Make sure you have a subclass for UITableViewCell that have an IBOutlet that connects to the collection view
cell.collectionView.tag = indexPath.row //Note that this only works in your situation where the table view have only 1 section.
/...
}
Then split your array into a 2D array:
var images = [
["11.png", "12.png", "13.png"],
["21.png", "22.png", "23.png"],
["31.png", "32.png", "33.png"],
["41.png", "42.png", "43.png"],
["51.png", "52.png", "53.png"],
["61.png", "62.png", "63.png"],
["71.png", "72.png", "73.png"],
["81.png", "82.png", "83.png"],
["91.png", "92.png", "93.png"],
["101.png", "102.png", "103.png"]
]
Finally read the array in the collection view like:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
/...
let myCellImage = UIImage(named: images[myCell.tag][indexPath.item])
/...
}

Related

CollectionView indexPath.row is not correct? (Inside TableViewCell)

I have a collection view that I want the indexPath.row to. However, whenever I try to print/display the indexPath.row number, it's off. It's a horizontal collection view, so when I try to page right, it goes from: 0, 2, 3, 4, 5 and going backwards it jumps to 5,3,2,1,1,1. It's also varies each time.
Currently the collectionView is inside a tableViewCell. The data is getting loaded off of Firebase database.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userList.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FeedCollectionViewCell
pageController.currentPage = indexPath.row
pageController.numberOfPages = userList.count
return cell
}
Setting Prefetching enabled to false in storyboard worked.

How to get uiTableView cell index on didSelectItem of collectionView cell

I have a tableView, which cell's contains collectionView. Now I want to get the tableview row index when I select any cell of collection view cell
Create a subclass of UICollectionView and add an attribute to it.
class MyCustomCollectionView: UICollectionView {
var parentTableViewIndexPath: IndexPath?
}
Use this collection view in your tableview cell
class MyCustomTableViewCell: UITableViewCell {
#IBOutlet weak var customCollectionView: MyCustomCollectionView!
}
In your table's cellForRow method, set the indexPath attribute
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "IDENTIFIER", for: indexPath) as! MyCustomTableViewCell
cell.customCollectionView.parentTableViewIndexPath = indexPath
//Any additional customisation
return cell
}
In your collectionView's didSelectItemAt, access the indexPath like this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let tableIndexPath = (collectionView as? MyCustomCollectionView)?.parentTableViewIndexPath else { return }
}
Inside cellForRowAt
cell.collectionView.tag = indexPath.row

Collection view inside table view

I have the following problem.
In my project I have a table view with multiple sections and one row in every section. Inside row I have a collection view.
Collection view items count depending on section in which the collection is located.But I do not understand how to access section number when I call func numberOfItemsInSection for collection view.
Here is my code:
ViewController.swift
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
TableCell.swift
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//TODO ?????? How can i get here section of table view
}
Thanks!
Create an array in UITableViewCell subclass and use that array in collectionview datasource methods
class CustomCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
var collectionData = [String]()
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionData.count
}
}
In tableView cellForRowAt method assign value to the array and reload colletion view
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as? CustomCell
cell?.collectionData = []//assign data here based on indexPath.section
cell?.collectionView.reloadData()
return cell!
}
Here you can use object oriented approach, in Your tableview cell create a variable tableSectionNumber. Like
class YourCell: UITableViewCell {
public var tableViewSectionNumber: Int = 0;
....
Now here in collectionView numberOfItemsInSection method, you can access it
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//TODO ?????? How can i get here section of table view
self.tableViewSectionNumber // its here
}
Now you can set this value in the cell in your ViewController, when you are populating the cell in TableView cellForRowItem method, Like
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.tableViewSectionNumber = indexPath.section // here you set the section number in cell
}

Index path of a collection view cell that is inside of a table view cell

I have a UICollectionView nested inside of a table view cell. How can I get the index path of the horizontal row of the collectionview cell? I tried to use
let index = cell.tag
print(index as Any)
to print which index was being selected not knowing that it will print a value of zero no matter what cell I select. I apologize that I am not experienced with collection views. Any help is much appreciated. Thanks.
You should design a protocol handling nested UIElement interactions. It makes your mind clearer and allocate better addresses
class ViewwithTable:UIViewController,UITableViewDataSource,collectionCell_delegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "temp", for: indexPath) as! NestedViewwithCollection
cell.delegate = self
return cell
}
func didPressed(indexPath: IndexPath) {
//the pressed index!
}
}
class NestedViewwithCollection:UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate{
var delegate:collectionCell_delegate?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let del = delegate{
del.didPressed(indexPath: indexPath)
}
}
}
protocol collectionCell_delegate {
func didPressed(indexPath:IndexPath)
}
Use this code for tableView
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return model.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
return cell
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
guard let tableViewCell = cell as? TableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
}
Collection View
extension ViewController: UICollectionViewDelegate,UICollectionViewDataSource
{
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return model[collectionView.tag].count
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",
forIndexPath: indexPath)
cell.backgroundColor = model[collectionView.tag][indexPath.item]
return cell
}

Cell takes index of its previous cell - Collectionview inside Tableview

I want to dynamically add collection view inside tableview. I have make following code.
A cell class for collectionview
class NewsFeedCollectionViewCell : UICollectionViewCell{
#IBOutlet weak var imageViewSlider: UIImageView!
}
Than assign collectionview in Tableview cellforrow at indexpath
cell.collectionViewNewsFeed.tag = indexPath.row
cell.collectionViewNewsFeed.reloadData()
Than added following delegates of collectionview
// MARK: - Collection view Delegates / Datasources
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (mutableArrayNewsFeed[collectionView.tag]["images"] as! NSArray).count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("NewsFeedCollectionViewCell", forIndexPath: indexPath) as! NewsFeedCollectionViewCell
print("tag : \(collectionView.tag) , Row : \(indexPath.row)")
let img = (mutableArrayNewsFeed[collectionView.tag]["images"] as! NSArray)[indexPath.row] as? String ?? "imgLoginScreenLogo"
cell.imageViewSlider.image = UIImage(named: img)
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("Collection View Row : \(indexPath.row)")
}
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
return collectionView.frame.size
}
Its adjusting properly but the indexes gets changes while i scroll the collectionview. For ex, I scroll collectionview upto 3 cell than i go to the tableview 4th index than it also set the index of 4th index of collectionview to 3rd.
Simply want to add collection view with multiple images inside Table view. I have added, but after scrolling the collection view to 3rd image on 1st cell of tableview, i move to 4th cell of Tableview, there also the collectionview gets scrolled automatically upto 4th cell.
Need to get out of this.
There was an issue with the indexpath, I get the solution by keeping the indexpath in an array.
Refer Following link
https://github.com/ashfurrow/Collection-View-in-a-Table-View-Cell