UICollectionView prepareForSegue indexPathForCell is nil iOS 9 - ios

The problem is this line return nil:
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell)
For that reason I can't pass any information, The identifier is set and the delegate is set.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell) {
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[indexPath.row]
}
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: collectionView.cellForItemAtIndexPath(indexPath))
}
Any help?

The problem is how to try to get the cell back. You must pass the cell in the performSegueWithIdentifier and then recover it in prepareForSegue.
Here is the code:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: collectionView.cellForItemAtIndexPath(indexPath))
}
And then
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
if let cell = sender as? UICollectionViewCell{
let indexPath = self.collectionView!.indexPathForCell(cell)
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[indexPath.row]
}
}
}
Hope it helps!

Try Like this..
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: indexPath)
}
and get your indexpath like this...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
let aIndPath = sender as! NSIndexPath
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[aIndPath.item]
}
}

The problem is the var collectionView is not reference in my ViewController for that reason always return nil. My mistake thanks you for your answers.
#IBOutlet weak var collectionView: UICollectionView!

Related

CollectionView Segue finding nil on receiving ViewController

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)
}

How to send a selected collectionview cell to another view controller (ios)?

I'm being able to detect the selected row (image) in my collection view, But I need to send it to another view controller. Here is a part of the code :
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CollectionViewCell {
cell.cellImage.image = UIImage(named: images[indexPath.row])
return cell
} else {
return CollectionViewCell()
}
}
//Printinig the selected image ID in console
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
SelectedItem = indexPath.row + 1
print(SelectedItem)
}
//Navigate to MPViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController = segue.destination as! MPViewController
DestViewController.labelText = String(SelectedItem)
}
}
Initialize a variable first
var imageToPass: UIImage!
Then update didSelectItemAt func
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
SelectedItem = indexPath.row + 1
print(SelectedItem)
self.imageToPass = UIImage(named: images[SelectedItem])
performSegue(withIdentifier: "TargetVC", sender: imageToPass) //here you give the identifier of target ViewController
}
Go to your TargetVC and initialize a variable
var getImage: UIImage!
Then override the function in previous VC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TargetVC" {
if let targetVC = segue.destination as? TargetVC {
if let imageToPass = sender as? UIImage {
TargetVC.getImage = imageToPass
}
}
}
}
//Printinig the selected image ID in console
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
self.SelectedItem = indexPath.row + 1
self.selectedImage = UIImage(named: images[indexPath.row]);
print(SelectedItem)
}
//Navigate to MPViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController = segue.destination as! MPViewController
DestViewController.imageSelected = self.selectedImage;
DestViewController.selectedItem = String(self.SelectedItem);
}
Now in MPViewController you can use the data self.imageSelected and self.selectedItem as per your requirements.
Take one instance variable in your destination class and set value of it in prepare for segue and then in viewDidload set that string to your label's text like,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController = segue.destination as! MPViewController
DestViewController.yourText = String(SelectedItem)
}
ans in viewDidload
yourLabel.text = yourText

Segue from CollectionViewCell to Another View Controller Passing IndexPath

I'm trying to pass the indexPath of a cell tapped in a UICollectionView to another view controller. I can't seem to get the indexPath of what was selected and segue it to the next view controller
I get this error: "Could not cast value of type Post to PostCell"
View Controller #1:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let post = posts[indexPath.row]
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PostCell", forIndexPath: indexPath) as? PostCell {
cell.configureCell(post)
}
return cell
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedPost: Post!
selectedPost = posts[indexPath.row]
performSegueWithIdentifier("PostDetailVC", sender: selectedPost)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
//Error here: Could not cast value of Post to PostCell
if let selectedIndex = self.collection.indexPathForCell(sender as! PostCell){
print(selectedIndex)
}
if let detailsVC = segue.destinationViewController as? PostDetailVC {
if let selectedPost = sender as? Post {
print(selectedIndex)
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndex
}
}
}
}
View Controller #2:
var indexNum: NSIndexPath!
override func viewDidLoad() {
super.viewDidLoad()
print(indexNum)
}
You are passing a Post instance which doesn't match the expected PostCell instance.
I recommend to pass the index path
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("PostDetailVC", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
guard let selectedIndexPath = sender as? NSIndexPath,
detailsVC = segue.destinationViewController as? PostDetailVC else { return }
print(selectedIndexPath)
let selectedPost = posts[selectedIndexPath.row]
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndexPath
}
}
You are passing a Post and not a PostCell as sender. You don't need that anyway, as the collectionView keeps track of selected items.
Try this:
if let selectedIndex = self.collection.indexPathsForSelectedItems()?.first {
print(selectedIndex)
}
It's because you are giving argument which has type of Post and you are trying to cast it as PostCell. Which will not work.

Preparing segue in Collection View

I have collection view implemented but have an error for the segue. I am trying to hand the image to another view controller using a segue. This is the code for it.
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showImage", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImage"
{
let indexPaths = self.collectionView!.indexPathsForSelectedItems()!
let indexPath = indexPaths[0] as NSIndexPath
let vc = segue.destinationViewController as! NewViewController
vc.image = self.imageArray[indexPath.row]!
vc.title = self.appleProducts[indexPath.row]
}
}
}
However I am having an error at collectionView!.indexPathsForSelectedItemssaying that Could not find member indexPathsForSelectedItems. Why is this happening and how should it be changed. Thank you
I have mode some changes to your code
Add following changes in your code
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showImage", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImage"
{
let indexPath : NSIndexPath = sender as! NSIndexPath
let vc = segue.destinationViewController as! NewViewController
vc.image = self.imageArray[indexPath.row]!
vc.title = self.appleProducts[indexPath.row]
}
}

Refresh same view controller with new data?

I have a song page with recommended songs in a table view. When a user clicks on a recommended song, I want to essentially reload the song page with the new data. To do that, I'm using this method, with a segue from the cell to its own view controller:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let newSong = recommendedTitles[indexPath.row]
self.performSegueWithIdentifier("refreshSong", sender: newSong)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let newSong:String = sender as! String
let song = segue.destinationViewController as! SongViewController
song.search = newSong
}
}
But I'm getting an error at let newSong:String = sender as! String, that it could not cast value of type recommendationCell to NSString. Is the best way to do all of this with the aforementioned tableView methods?
You do not have to declare global variable.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("refreshSong", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let indexPath = tableView.indexPathForSelectedRow()
let song = segue.destinationViewController as! SongViewController
song.search = recommendedTitles[(indexPath?.row)!]
}
}
you try this. Take the variable newSong in declaration section
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
newSong = recommendedTitles[indexPath.row]
self.performSegueWithIdentifier("refreshSong", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let song = segue.destinationViewController as! SongViewController
song.search = newSong
}
}

Resources