How to get uiTableView cell index on didSelectItem of collectionView cell - swift

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

Related

Textfield values deleted when scrolling tableview?

I have tableview cell with a textfield but when I add new row and scroll tableview up or down disappeared textfield values deleted. I make lots of research about that previous question about that in 2015 and its not answered correctly. How can I fix this issue? How can I use textfield delegate method if it is working for this? Here my code:
var i = 0
while i <= taskArrForRead.count {
let indexPath = IndexPath(row: i, section: 0)
let cell = self.tableView.cellForRow(at: indexPath) as? taslakDuzenlemeCell
if let item = cell?.taslakTextField.text! {
arrayOfNames.append(item)
}
i = i + 1
}
In this code I get all textfield values from tableview but if tableview scroll disappeared values turn with default values. How can I fix it? Thanks.
Here my tableview code:
extension taslakOlusturmaController: UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return taskArrForRead.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "taslakCell", for: indexPath) as! taslakDuzenlemeCell
cell.taslakTextField.text = taskArrForRead[indexPath.item]
cell.taslakTextField.delegate = self
return cell
}
func textFieldDidEndEditing(_ textField: UITextField) {
print(textField.text!)
self.arrayOfNames.append(textField.text!)
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "taslakCell", for: indexPath) as! taslakDuzenlemeCell
cell.taslakTextField.text = taskArrForRead[indexPath.item]
print(arrayOfNames[indexPath.item])
}
}
With textfield delegate method I can get deleted textfield values but I can't bring it again to textfield. User can't see value after scroll again also I can get deleted values with didEndDisplaying cell method too.
You could use the method PrepareForReuse to set the text back when the cell recreated again.

How to add table view cell with a button inside of another table view cell?

I am trying to make a to-do list app and I am having trouble trying to add subtasks to my main to-do tasks. I have a button inside each table view cell, when this button is pressed I want it to add another table view cell that I can type and save a "subtask" on.
//set up tableView row amount
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return taskData.count
}
//set up what is in the tableView row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//This is for a main task
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! CustomTableViewCell
cell.label.text = taskData[indexPath.row]
return cell
}
Use delegates to pass data from cells to your ViewController, and reload the tableView.
CustomTableViewCell:
protocol CustomTableViewCellDelegate: class {
func customTableViewCellButtonClicked(_ cell: CustomTableViewCell)
}
class CustomTableViewCell: UITableViewCell {
weak var delegate: CustomTableViewCellDelegate?
func buttonClicked() {
self.delegate?.customTableViewCellButtonClicked(self)
}
}
ViewController:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! CustomTableViewCell
cell.label.text = taskData[indexPath.row]
cell.delegate = self
return cell
}
func customTableViewCellButtonClicked(_ cell: CustomTableViewCell) {
// add the task you need from that cell to your tasks list.
taskData.append(....)
//reload your tableView
self.tableView.reloadData()
}

How to call More than one CollectionView in collection View data Source on table view cell

I have 2 collection view in table view cells and each collection view has Outlet in own table view cell . how i can call and use this two collection view in cellForItemAt method in view controller.
if (collectionView == self.amazing_Collection) // doesnt work
this is table view methods in view controller
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = indexPath.section
if section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "searchCell", for: indexPath) as! searchCell
return cell0
}else if section == 1 {
let cell1 = tableView.dequeueReusableCell(withIdentifier: "slideCell", for: indexPath) as! slideCell
return cell0
and this is collection view method for fill image and labels
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
"amazingCollecionCell", for: indexPath) as! amazingCollecionCell
////this is work correctly
return cell
return cell
//here iwant to say if this collection view execute under lines
let cell_Just_Here = collectionView.dequeueReusableCell(withReuseIdentifier: "justhereproductscell", for: indexPath) as! JustHereProductsCell
//lable fill
return cell_Just_Here
}
}
When tableview's data source method is called, set the collection view's tag value as indexPath.row(cell's index path). By this in the collection view's datasource method you will be able to identify the collection view with the tag value and set the cells accordingly.
Hope this helps.

Can I do transition in CollectionCell Class?

I want to transition another ViewController Class when tablViewCell tapped. (TableView in CollectionView Cell)
so,I want to write to transition Code in tableViewCell Class.
How should I do?
You need to assign collectionview delegate to the view controller class inside the tableview cellforrow method. And assign tableview cell indexpath.row to its collectionview tag.
In collectionview didselect method write the transition Code.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ...
cell.collectionView.tag = indexPath.row
cell.collectionView.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("selected collectionview cell indexpath \(indexPath) in table view cell row \(collectionView.tag)")
//push to next view controller from here
}
}

Images In a Collection View

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])
/...
}