I am trying to send a label that is contained within a collection view cell to another view controller with a segue.
My plan is that when a user taps on the collection view cell, the app then segues to the next view controller where the navigation bar's title displays the text of the label in the collection view cell selected.
I have tried this:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CCCollectionViewCell
//itemSelected = items[indexPath.row] as String
itemSelected = cell.pLabel.text!
print(itemSelected)
}
and in prepareForSegue I have not written any code as I am not sure how this works.
I commented out the block '..items[indexPath.row] as String' because it won't show the label and added the print function to see what will output but it only outputs the name given in the storyboard.
I am very new to Xcode so am not familiar with didSelect and prepareForSegue. All I am trying to do is to send the text within a collection view cell to another view controller with a segue.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "contentVideoSegue", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "contentVideoSegue"{
let selectedIndexPath = sender as? NSIndexPath
let videoContentVC = segue.destination as! VideoContentController
videoContentVC.text = items[selectedIndexPath.row] as String
}
}
in the hope of helping :)
From your code you are not calling the performSegue(withIdentifier:sender:) so you probably have created segue from the CollectionViewCell to DestinationViewController. So get the indexPath using this cell in prepareForSegue method.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let cell = sender as? UICollectionViewCell,
let indexPath = self.collectionView.indexPath(for: cell) {
let vc = segue.destination as! SecondViewController //Cast with your DestinationController
//Now simply set the title property of vc
vc.title = items[indexPath.row] as String
}
}
So you don't need to set up the cell in didSelect because you're already doing that in cellForItemAtIndexPath.
Rather you'll want to call performSegue(withIdentifier: "SegueName", sender: indexPath) in your didSelectItemAtIndexPath. Then in your prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let indexPath = sender as? IndexPath else { return }
let collectionCell = collectionView.cellForItem(at: indexPath)
let textToPass = collectionCell.textLabel.text
let detailVC = segue.destination as? DetailViewController
detailVC.passedInString = textToPass
}
Related
I am trying to perform a segue and pass data to detailViewController from my cell when tapped. I have tried with dummy data and I can pass them to detailScreen, however I would like to pass data that are related to cells.When I tapped a cell I get this error "Could not cast value of type ViewController to MovieCell" with line let selectedItem = ...
Thanks for your time and effort
Here is my code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detailSegue"
{
let destination = segue.destination as! DetailViewController
let selectedItem = collectionView.indexPath(for: sender as! MovieCell)!
let character = characters[selectedItem.item]
destination.detailName = character.name
destination.detailGender = character.gender
destination.detailSpecies = character.species
destination.detailStatus = character.status
}
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "detailSegue", sender: self)
}
try use:
collectionView.indexPathsForSelectedItems.first
instead
collectionView.indexPath(for: sender as! MovieCell)!
Also I wanna recommend for you my library for such situations: Link
I have the following situation:
ExploreViewController is a table view controller with CategoryTableViewCell (child class of UITableViewCell)
The CategoryTableViewCell has a CollectionView with UICollectionViewCells.
When a user clicks on a UICollectionViewCell, I would like to segue ExploreViewController to BookListViewController based on the uICollectionViewCell data. Each UICollectionViewCell stands for a separated category.
How can I do this using swift? I tried using delegate protocol, but when I call performSegue inside the delegate function inside the ExploreViewController, I get an error.
In CategoryTableViewCell
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("test12")
self.delegate?.didSelectInEmbeddedCollection()
}
}
protocol CategoryTableViewCellDelegate {
func didSelectInEmbeddedCollection()
}
In ExploreViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("test14")
if segue.identifier == "toBookListFeatured",
let destination = segue.destination as? BookListViewController,
let selectedIndexPath = self.tableViewFeaturedCats.indexPathForSelectedRow,
let selectedCell = self.self.tableViewFeaturedCats.cellForRow(at: selectedIndexPath) as? CategoryTableViewCell
{
let collectionView = selectedCell.collectionView
let indexPathC = collectionView?.indexPathsForSelectedItems?.first
let cell = collectionView?.cellForItem(at: indexPathC!) as? CategoryCollectionViewCell
destination.data = cell!.label.text
} else {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
let dc = segue.destination as! BookListViewController
dc.data = self.tableRowData["name"] as! String;
dc.searchByCategory = true
}
}
}
extension ExploreViewController: CategoryTableViewCellDelegate {
func didSelectInEmbeddedCollection() {
performSegue(withIdentifier: "toBookListFeatured", sender: nil)
}
}
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 3 years ago.
My scenario, I am trying to get JSON data using codable format. I need to pass the decoder value to another view controller after click the Tableview custom cell. I don't know how to do that, I seen some example but its not clear.
My Code below
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//print("You tapped cell number \(indexPath.row).")
let section = isFiltering ? filteredSections[indexPath.section] : sections[indexPath.section]
let item = section.result[indexPath.row]
print("\(item)")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "secondviewcontroller") as! SecondViewController
vc.dataset = item
let navigationController = UINavigationController(rootViewController: vc)
self.present(navigationController, animated: true, completion: nil)
}
This is a segue from a cell to a ViewController that performs on cell selection, for this you want to do:
var selectedItem: Item?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let secondViewController = (segue.destination as? UINavigationController)?.topViewController as? SecondViewController {
if let item = selectedItem {
secondViewController.dataset = selectedItem
}
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Here you are only setting the item variable to the selected one so you can grab it in the prepare func
// No need to call the segue because the storyboard linkage from cell to controller will be used to call the segue
let section = isFiltering ? filteredSections[indexPath.section] : sections[indexPath.section]
selectedItem = section.result[indexPath.row]
}
This is a segue from a ViewController to a ViewController, for this you want to:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let secondViewController = (segue.destination as? UINavigationController)?.topViewController as? SecondViewController {
if let item = sender as? Item {
secondViewController.dataset = selectedItem
}
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Here the controller will not automatically perform the segue on selection
// You call the performSegue function and send the selected item as sender
// The item will be available in the prepare function
let section = isFiltering ? filteredSections[indexPath.section] : sections[indexPath.section]
performSegue(withIdentifier: "secondviewcontroller", sender: section.result[indexPath.row])
}
I am trying to send the charName String from AvengersViewController to CharViewController.
I am using a collection view in AvengersViewController. CharName is a label in CharViewController.
What I am trying works perfectly with a table view but I can't get it to work using collectionViews...
I am using "lastItemSelectedA" to indicate the index of the label from my avengers array. The passing of data works... I can't get the index of the collectionViewItem to pass with the first segue, thus, making it null. By using the default value of 0 I have been able to notice that it does work, however, it does not change the value of lastItemSelectedA when the cell is pressed but after... Or at least it does not update the variable.
I have already tried at least 5 implementations from solutions on stack.
extension AvengersViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
lastItemSelectedA = indexPath.item
//self.performSegue(withIdentifier: "openToCharA", sender: indexPath.item)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let identifier = segue.identifier else { return }
switch identifier {
case "openToCharA":
if let destination = segue.destination as? CharViewController {
destination.charName = avengers[lastItemSelectedA ?? 0].name
}
//destination.sounds = sounds
//guard let indexPath = collectionView.indexPathsForSelectedItems else {return}
//let sounds = fallen[lastItemSelectedF!].sounds
default:
print("unexpected segue identifier")
}
}
If prepare(for segue is called then you've connected the segue from the collection view cell (rather than from the controller).
In this case delete
var lastItemSelectedA : Int
and
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
lastItemSelectedA = indexPath.item
//self.performSegue(withIdentifier: "openToCharA", sender: indexPath.item)
}
and get the index path of the collection view cell from the sender parameter
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "openToCharA" {
let cell = sender as! UICollectionViewCell
let indexPath = collectionView.indexPath(for: cell)!
let destination = segue.destination as! CharViewController
destination.charName = avengers[indexPath.item].name
}
}
Force unwrapping the optionals is fine in this case. The code must not crash if everything is hooked up correctly and if it does it reveals a design mistake.
I have a collection view that is selecting an Item in its index and performing a segue to the next ViewController. When the next ViewController is presented, the value of my object is nil.
Here is the call in the collectionView:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let adViewVC = storyboard?.instantiateViewController(withIdentifier: adViewPageID) as? AdViewPageVC else {return}
let adChoice = adArray[indexPath.row]
adViewVC.advertisement = adChoice
performSegue(withIdentifier: adViewPageSegue, sender: self)
}
Note that the guard statement is going through and if I print a value from the adArray it has value in this function.
After I perform the segue which does open the right ViewController the advertisement object is always nil.
var advertisement : Advertisement!
override func viewDidLoad() {
super.viewDidLoad()
let title = advertisement.title
print(title)
}
This is never getting the value of the object even when I can see that it has value during the assignment on the didSelectItem function for the collection view.
What am I missing here?
When the user taps on the collectionViewCell, the app should perform segue with an indexPath as a sender:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: adViewPageSegue, sender: indexPath)
}
And prepare all of neccessary things in the prepare(for:sender:) method. And you don't have to init a viewController from the storyboard. segue.destination is enough.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == adViewPageSegue {
guard let adViewVC = segue.destination as? AdViewPageVC else {return}
let indexPath = sender as! IndexPath
let adChoice = adArray[indexPath.row]
adViewVC.advertisement = adChoice
}
}
}
You should be setting the advertisement variable in a prepare(for:sender:) function. The view controller that you are creating in the didSelect function is not being used.
Add something like this:
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewController = segue.destination as? PlayerViewController {
let adChoice = adArray[sender]
viewController.advertisement = sender as? STZMediaItem
}
}
And update your didSelect function to be:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: adViewPageSegue, sender: indexPath)
}