I'm trying to modify a variable with the number of the row selected in a UITableView, so that I can access that variable from another UIViewController but when I'm setting the value of the variable with the row number in func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) it appears that the variable is not changed.
I've a View Controller with an UITableView, what I'd like is to select a row, then, when I click on a button a Popoverview appear where I can parameterize things linked to the row I selected.
Here is what I've done :
import UIKit
class Settings: UIViewController , UITableViewDataSource,
UITableViewDelegate{
#IBOutlet weak var tableView: UITableView!
var RowSelected = Int()
let animals = ["Tap", "Double Tap", "Long press", "Swipe up", "Swipe down", "Swipe left", "Swipe right", "Zoom", "Unzoom"]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell"/*Identifier*/, for: indexPath as IndexPath)
cell.textLabel?.text = animals[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animals.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
RowSelected = indexPath.row
print(RowSelected)
}
}
It print the row perfectly here, but when I access it from the other ViewController it's always equal to 0.
import UIKit
class GestureConfiguration: UIViewController,
UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var actionSelected: UILabel!
let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard
var items = ["1", "2", "3", "4", "5"]
var index : Int = 1
var scVC = Settings()
let gestes = ["Tap", "Double Tap", "Long press", "Swipe up", "Swipe down", "Swipe left", "Swipe right", "Zoom", "Unzoom"]
#IBOutlet weak var tableView: UITableView!
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 9
}
// tell the collection view how many cells to make
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
collectionView.allowsMultipleSelection = true
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.myLabel.text = self.items[indexPath.item]
cell.backgroundColor = UIColor(red:0.13, green:0.37, blue:0.58, alpha:0.7)
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
let cell = collectionView.cellForItem(at: indexPath)
print("You selected cell #\(indexPath.item + 1) section \(indexPath.section + 1)")
cell?.backgroundColor = UIColor(red:0.08, green:0.28, blue:0.45, alpha:1.0)
///////// HERE \\\\\\\\\\
actionSelected.text = String(scVC.RowSelected)
print(scVC.RowSelected)
// Always print 0, same for the label.
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
// handle tap events
let cell = collectionView.cellForItem(at: indexPath)
print("You unselected cell #\(indexPath.item + 1) section \(indexPath.section + 1)")
cell?.backgroundColor = UIColor(red:0.13, green:0.37, blue:0.58, alpha:0.7)
}
What am I missing? When I hardcode a value to RowSelected (like 99), I'm able to see 99 in my second ViewController.
Thanks for your help.
EDIT for Akhilrajtr :
class Settings: UIViewController , UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var tableView: UITableView!
var RowSelected = Int()
let animals = ["Tap", "Double Tap", "Long press", "Swipe up", "Swipe down", "Swipe left", "Swipe right", "Zoom", "Unzoom"]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell"/*Identifier*/, for: indexPath as IndexPath)
cell.textLabel?.text = animals[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animals.count
}
//Not overriding any function,
Override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toPopover") {
var secondViewContr = segue.destination as! GestureConfiguration
secondViewContr.scVC = self
}
}
}
And:
class GestureConfiguration: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var actionSelected: UILabel!
var scVC = Settings()
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
let cell = collectionView.cellForItem(at: indexPath)
print("You selected cell #\(indexPath.item + 1) section \(indexPath.section + 1)")
cell?.backgroundColor = UIColor(red:0.08, green:0.28, blue:0.45, alpha:1.0)
actionSelected.text = String(scVC.RowSelected)
print(scVC.RowSelected)
}
In GestureConfiguration create one variable of Settings class and then access it in your tableViewDelegate function.
In Settings class override function prepareforsegue as
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let gestuedistination = segue.destination as? GestureConfiguration {
gestuedistination.settings = self
}
}
In GestureConfiguration class declare
#IBOutlet weak var actionSelected: UILabel!
var settings:Settings?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
let cell = collectionView.cellForItem(at: indexPath)
print("You selected cell #\(indexPath.item + 1) section \(indexPath.section + 1)")
cell?.backgroundColor = UIColor(red:0.08, green:0.28, blue:0.45, alpha:1.0)
actionSelected.text = String(settings!.RowSelected)
print(settings!.RowSelected)
}
if you are using segue to show the second view controller, then in Settings view controller implement the below method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "your segue id") {
var secondViewController = segue.destinationViewController as! GestureConfiguration
secondViewController.scVC = self
}
}
if you just need the selected row identifier, then create a var in GestureConfiguration and set it from prepareForSegue
It looks to me like the issue is because you are instantiating a new view controller in var scVC = Settings(). Instead, whenever you create this GestureConfiguration view controller, you should pass the reference to the proper Settings view controller so that RowSelected is what you want.
(Although it would be better just to pass RowSelected itself instead of the entire Settings view controller unless you need the view controller for other things)
Make globlal object of setting var globalSetVC = Settings() and in setting view controller save rowSelect like this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath:IndexPath) {globalSetVC.RowSelected = indexPath.row print(globalSetVC.RowSelected)}
use it where ever require as globalSetVC.RowSelected
Related
I wish to pass data through segue from a collectionViewCell embedded in a TableViewCell;
Also from a Button embedded in a TableViewCell
Here is the sample code :
Here is the TableViewCell's class :
class PopularCell: UITableViewCell {
#IBOutlet weak var ViewAllButton: UIButton!
#IBOutlet weak var PopularEvents: UILabel!
#IBOutlet weak var EventCollection: UICollectionView! // EMBEDDED COLLECTIONVIEW
var events = [Events]()
override func awakeFromNib() {
super.awakeFromNib()
// EMBEDDED BUTTON
ViewAllButton.setIcon(prefixText: "View All ", prefixTextColor: .blue, icon: .typIcons(.chevronRight), iconColor: .blue, postfixText: " ", forState: .normal, iconSize: 24) // EMBEDDED BUTTON
EventCollection.delegate = self
EventCollection.dataSource = self
}
extension PopularCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return events.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = EventCollection.dequeueReusableCell(withReuseIdentifier: "EventCell", for: indexPath) as! EventCell
let event = events[indexPath.row]
print("Event Name:\(event.event_name)")
cell.event = event
return cell
}
}
Here is the ViewController(TableView Delegate & DataSource) class :
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return groupedEventArray.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 245
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PopularCell", for: indexPath) as! PopularCell
let (category, events) = groupedEventArray[indexPath.row]
cell.ViewAllButton.addTarget(self, action: #selector(VenueViewController.ViewAll(_:)), for: .touchUpInside)
cell.PopularEvents.text = category
cell.events = events
return cell
}
#objc func ViewAll(_ sender:UIButton!) {
self.performSegue(withIdentifier: "ViewEvents", sender: sender)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "ViewEvents") {
let destination = segue.destination as? EventListController
destination?.navigationItem.title = "Event Category"
}
else if(segue.identifier == "ViewEventDetails") {
if let collectionCell: EventCell = sender as? EventCell {
if let _: UICollectionView = collectionCell.superview as? UICollectionView {
let destination = segue.destination as? EventDetailViewController
destination?.navigationItem.title = "Event Details"
}
}
}
}
How do I configure the func prepare so as to pass data through the "ViewEvents" & "ViewEventDetails" segue identifiers accordingly
I have created a tableView with two different labels and one textfield. Depending on the indexPath in which is selected the labels will display different text according to the array. I have created a CocoTouch Class file and made it type TableViewCell.
TableViewCell.swift
import UIKit
class Driver_Navigation_TableViewCell: UITableViewCell {
#IBOutlet weak var orderTextField: UITextField!
#IBOutlet weak var adressLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
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
}
}
ViewController.swift
class ViewController: UIViewController, MGLMapViewDelegate, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
var allCellsText = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Driver_Navigation_TableViewCell
cell.adressLabel.text = passengersAdress[indexPath.row]
cell.nameLabel.text = passengersName[indexPath.row]
cell.orderTextField.placeholder = "\(indexPath.row + 1)."
return(cell)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! Driver_Navigation_TableViewCell
cell.orderTextField.tag = indexPath.row
cell.orderTextField.delegate = self // theField is your IBOutlet UITextfield in your custom cell
return cell
}
func textFieldDidEndEditing(textField: UITextField) {
allCellsText.append(textField.text!)
print(allCellsText)
}
}
You cant have duplicate UITableViewDataSource and UITableViewDelegate methods it won't work like that.
Also in your code you have not set the delegate for the textField in both the cellForRowAtIndexPath() methods.
If you want to have two table view in a single controller try the following
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAtIndexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Driver_Navigation_TableViewCell
if tableView == self.tableView1 {
cell.adressLabel.text = passengersAdress[indexPath.row]
cell.nameLabel.text = passengersName[indexPath.row]
cell.orderTextField.placeholder = "\(indexPath.row + 1)."
}
else {
cell.orderTextField.tag = indexPath.row
}
cell.orderTextField.delegate = self
return(cell)
}
Create outlets for the Table View
I have a UICollectionView.
Inside each UICollectionViewCell of UICollectionView, I have a UITableView.
Inside each UITableViewCell of UITableView, I have a UIButton.
When clicking on UIButton or UITableViewCell, I want to change the image of UIButton.
Here is my UICollectionView:
Here is my code:
SurveyQuestionsCollectionViewController.swift
import UIKit
class SurveyQuestionCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var survey_questions: [Dictionary<String, Any>] = []
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.register(UINib.init(nibName: "SurveyQuestionsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "survey_cell")
let layout = self.collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
let collectionViewSize = self.collectionView?.frame.size
let itemWidth = Int((collectionViewSize?.width)!)
let itemHeight = Int((collectionViewSize?.height)!)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
common()
//result is coming from API call which I have deleted as it is not necessary to describe my problem
self.survey_questions = result["survey_questions"] as! [Dictionary<String, Any>]
self.collectionView?.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
common()
return survey_questions.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var question = survey_questions[indexPath.item]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "survey_cell", for: indexPath) as! SurveyQuestionsCollectionViewCell
cell.setValues(question: question["question"]! as! String,
answers: question["answers"]! as! [Dictionary<String, Any>])
return cell
}
func common() {
self.collectionView.setContentOffset(CGPoint(x: CGFloat(currentPosition) * self.collectionView.frame.size.width, y: 0), animated: true)
}
}
Here is my UICollectionViewCell and UITableView:
SurveyQuestionsCollectionViewCell.swift (at the back of .xib file)
import UIKit
class SurveyQuestionsCollectionViewCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate {
var answers: [Dictionary<String, Any>] = []
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
override func layoutSubviews() {
super.layoutSubviews()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView?.register(UINib.init(nibName: "SurveyQuestionsTableViewCell", bundle: nil), forCellReuseIdentifier: "survey_answer_cell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return answers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let answer = answers[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "survey_answer_cell", for: indexPath) as! SurveyQuestionsTableViewCell
cell.setRadioText(text: answer["answer"]! as! String)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "survey_answer_cell", for: indexPath) as! SurveyQuestionsTableViewCell
cell.setRadioImage(rowSelected: true, tableView: tableView)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "survey_answer_cell", for: indexPath) as! SurveyQuestionsTableViewCell
cell.setRadioImage(rowSelected: false, tableView: tableView)
}
func setValues(question: String, answers: [Dictionary<String, Any>]) {
self.questionLabel.text = question
self.answers = answers
self.tableView.reloadData()
}
}
Here is my TableViewCell
SurveyQuestionsTableViewCell.swift (at the back of .xib file)
import UIKit
class SurveyQuestionsTableViewCell: UITableViewCell {
#IBOutlet weak var radioButton: UIButton!
#IBOutlet weak var radioLabel: UILabel!
func setRadioText(text: String) {
radioLabel.text = text
}
func setRadioImage(rowSelected: Bool, tableView: UITableView) {
if rowSelected {
if let image = UIImage(named: "radioOn") as UIImage! {
self.radioButton.setImage(image, for: UIControlState.normal)
}
}
} else {
if let image = UIImage(named: "radioOff") as UIImage! {
self.radioButton.setImage(image, for: UIControlState.normal)
}
}
}
}
And here is my output:
Every time when I click on any TableCell, I would like to change the image of radioButton. But the image is not changing. I have also marked that code for changing image is executed but the image is not changing.
It's happening because you set cell.setRadioImage(rowSelected: false, tableView: tableView) code indidDeselectRowAtmethod look at your below code
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "survey_answer_cell", for: indexPath) as! SurveyQuestionsTableViewCell
cell.setRadioImage(rowSelected: false, tableView: tableView)
}
Just remove last line.
Updated :
For get cell in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) you need write below line
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// Your Stuff
let cell = tableView.cellForRow(at: indexPath) // Change this line
// Your Stuff
}
Instead of doing that much, follow the below step and do in short and clear.
Select your button and assign the image for its state.
a. for Default State
b. for Selected State
In SurveyQuestionsCollectionViewCell
var indexSelected : Int = 0
In cellForRowAt
if indexPath.row == indexSelected{
cell.button.isSelected = true
}
else{
cell.button.isSelected = false
}
in didSelectRowAt
self.indexSelected = indexPath.row
table.reloadData()
If still facing any issue then ask.
I've created a pretty simple test app. It includes a 3 view controllers. The main view controller has a table view, that uses custom cells. The other two view controllers are able to be accessed through the main view controller, each have collection views, and can go back to the main view controller.
Here is the memory issue. Anytime I click on any of the cells from the 3 view controllers, the memory usage increases. I ran the app while using the 'Leaks' profiling template and found no leaks. Also used the 'Allocations' profiling template, checked 2 of the view controllers (recorded the reference counts), and all the stored reference counts under my program were released.
I haven't been able to use the Debug Memory Graph as it keeps crashing Xcode...
Main View Controller
import UIKit
class TableViewController: UITableViewController, UISearchBarDelegate {
#IBOutlet weak var searchForTool: UISearchBar!
#IBOutlet weak var toolTable: UITableView!
var searchActive : Bool = false
var data = [" Alphabetical", " Numerical"]
var identities = ["A", "B"]
override func viewDidLoad() {
super.viewDidLoad()
toolTable.delegate = self
toolTable.dataSource = self
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.toolLabel.text = data[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
}
One of the other View Controllers (both identical)
import UIKit
class AlphabeticalViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var labelArray = [String]()
var identities = [String]()
override func viewDidLoad() {
super.viewDidLoad()
labelArray = ["Main", "Definitions", "Steps", "References", "Other"]
identities = ["C", "B", "B", "D", "E"]
self.navigationController?.setNavigationBarHidden(true, animated: false)
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return labelArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let myLabel = cell.viewWithTag(1) as! UILabel
myLabel.text = labelArray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
}
Custom Cell Class
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet weak var toolLabel: UILabel!
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
}
}
I will provide any other images if needed. Any help would be greatly appreciated.
Information I got using the allocation tool.
The commented out code is just a search feature that I don't need atm.
The problem seems to be inside the CustomCell, maybe some resources not deinitialized.
Do you have some code inside awakeFromNib() or setSelected(...)?
You have problem with your tableView and collection view. look at IBOutlets your tableView name is toolTable
#IBOutlet weak var toolTable: UITableView!
but inside your datasource for the tableView you're accessing the wrong tableView
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// this is the wrong tableView
/*
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
*/
// you should use the tableview which you have declared
let cell = toolTable.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.toolLabel.text = data[indexPath.row]
return cell
}
You have the same problem with your CollectionViewControllers as well.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//accessing wrong collectionView
/*
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
*/
// here you have to use self because your have named your collectionView the same as collectionView
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let myLabel = cell.viewWithTag(1) as! UILabel
myLabel.text = labelArray[indexPath.row]
return cell
}
Note: Your TableViewController and CollectionViewController are already Controllers. wondering why you have another tableView and collection view IBOutlets. Use one at a time
Firstly, I want to give credit to #totiG for pointing out that the problem could be with the navigation controller, and he was right.
There are other smaller memory issues, but the biggest by far had to do with my navigation. I kept pushing controllers onto the navigation stack, without popping them.
Here is the code for my final solution.
I replaced:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
With:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
if let navController = self.navigationController {
for controller in navController.viewControllers {
if controller is TableViewController {
navController.popToViewController(controller, animated: true)
}
}
}
} else {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
}
So now instead of pushing from controller to controller without popping any of them off of the stack, I pop all of the previous controllers up to the 'TableViewController' when 'Main' is clicked.
So I have a CollectionView inside my normal ViewController and if I select a cell and enter something in my textField and press the save Button it should update the nameLabel but I don't know how I can do that. Does anybody have a solution for this?
This is my current code:
private let reuseIdentifier: String = "Item"
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
ItemCollection.delegate = self
}
func textEnter() {
var text = textField.text
let indexPath = NSIndexPath()
let cell = ItemCollection.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ItemCell
cell.nameLabel.text = text
}
#IBAction func save(sender: AnyObject, cell: UICollectionViewCell) {
textEnter()
}
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var ItemCollection: UICollectionView!
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ItemCell
cell.backgroundColor = UIColor(red: 0/256, green: 128/256, blue: 255/256, alpha: 0.66)
cell.nameLabel.text = "Test1"
return cell
}
func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
}
My Cell:
class ItemCell: UICollectionViewCell {
#IBOutlet weak var nameLbl: UILabel!
}
There are a couple of things you'll need to do to make this work.
First, you need to preserve context of the clicked cell by storing a "reference" to it. The easiest thing would be to introduce three new variables - section and item. Using these values you'll be able to re-create index path object and reference the cell.
Second, instead of calling dequeueReusableCellWithReuseIdentifier(), you should construct the new Index Path object using the values saved in the previous step and call cellForItemAtIndexPath(_ indexPath: NSIndexPath). This may return a nil if the cell is not in view.
Note: this will set the label only when the user taps Save and the text will most likely be lost if the cell scrolls out of view and then back. In order to preserve this, you should store the entered value in a variable (or refer to the textbox directly) when creating the cell in cellForItemAtIndexPath method.
Modified code example (some of the syntax may be off, I'm doing this from memory):
private let reuseIdentifier: String = "Item"
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
ItemCollection.delegate = self
}
// Store the clicked item location
private section: Int = 0
private item: Int = 0
func textEnter() {
var text = textField.text
let indexPath = NSIndexPath(forItem: item inSection:section)
let cell = ItemCollection.cellForItemAtIndexPath(indexPath) as! ItemCell
cell.nameLabel.text = text
}
#IBAction func save(sender: AnyObject, cell: UICollectionViewCell) {
textEnter()
}
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var ItemCollection: UICollectionView!
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ItemCell
cell.backgroundColor = UIColor(red: 0/256, green: 128/256, blue: 255/256, alpha: 0.66)
cell.nameLabel.text = "Test1"
return cell
}
// Need to capture the tapped cell in here
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
section = indexPath.section
item = indexPath.item
}
func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
}