I have a collection view. each item should pass data to second view, in other world I want to pass current view to second view by navigationController.
class GroupsViewController: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate {
....
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
var group = self.items[indexPath.item]
var cat_title = group.cat_title
self.navigationController!.pushViewController(self.storyboard!.instantiateViewController(withIdentifier: "GroupSubOneTableViewController") as UIViewController, animated: true)
}
....
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("ooopps")
if (segue.identifier == "GroupSubOneTableViewController") {
let navController = segue.destination as! UINavigationController
let detailController = navController.topViewController as! GroupSubOneTableViewController
//detailController.currentId = nextId!
print("selected GroupSubOneTableViewController")
}
}
but in console log doesn't show anything!
You are mixing here two thing perfomSegue and pushViewController. performSegue(withIdentifier:sender:)
is called when you perform a segue using performSegue. So create one segue from your SourceVC to DestinationVC.
If you want to go with pushViewController then simply type cast UIViewController to your ViewController pass the data.
let vc = self.storyboard!.instantiateViewController(withIdentifier: "GroupSubOneTableViewController") as! GroupSubOneTableViewController
//pass vaue
vc.passStr = "Hello"
self.navigationController?.pushViewController(vc, animated: true)
It's not called because pushViewController doesn't perform a segue.
You need to call performSegue(withIdentifier: "GroupSubOneTableViewController", sender: self) instead of pushViewController.
Of course, you'll also need to set this up in your storyboard.
Related
I have two views that I would like to pass data from one view to the next. The first view is where I have the data that I would like to pass to the next view lets call it FirstViewController. However FirstViewController is embedded in a NavigationViewController and the secondViewController lets call it DestinationViewController.
I have tried this logic
IN FirstViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "DestinationViewController") {
if let vc: DestinationViewController = segue.destination as? DestinationViewController {
vc.id = id
}
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1
{
self.id = ((self.categorytArray.object(at: indexPath.row)as AnyObject).value(forKey: "id")as! NSNumber)
print(self.id)
self.performSegue(withIdentifier: "DestinationViewController", sender: self)
}
}
on destinationController I get empty value for id.
if I change in this line
if let vc: DestinationViewController = segue.destination as! DestinationViewController
I get this error:
Could not cast value of type 'UINavigationController' (0x10f9b3760) to 'Name.DestinationViewController' (0x1067f7c68).
2019-10-11 12:52:11.535900+0530 Name[2412:94748] Could not cast value of type 'UINavigationController' (0x10f9b3760) to 'Name.DestinationViewController' (0x1067f7c68).
Thanks in advance.
Since your View Controller is embedded in a Navigation Controller you need to retrieve it from the Navigation Controller as well
Try this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let nvc = segue.destination as? UINavigationController, let vc = nvc.viewControllers.first as? DestinationViewController else {
return
}
vc.id = id
}
First you retrieve the navigation controller (nvc), then you get your destination vc from it's list of child view controllers. Generally, the first controller in the Navigation Controller will be first in the array.
Also you don't need to provide a sender in your performSegue call.
self.performSegue(withIdentifier: "DestinationViewController", sender: nil)
You will notice that prepareForSegue has a sender parameter, but since you are accessing the information you want to pass to the DetailViewController through a class variable in your first View Controller, you're not using this sender parameter anyway.
Hope this helps
I have tableView within collectionView and i created using xib. I want to pushViewController when item is selected .I tried pushing the view controller in itemForRowAt method but it's not possible
class SecondTableView: UITableViewCell , UIcollectionViewDelegate ,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// let vc = DataTableViewController()
// vc.delegate = self
// vc.pushNav()
let memeVC = storyboard?.instantiateViewController(withIdentifier: "MemeViewController") as! MemeViewController
memeVC.imagePassed = image
navigationController?.pushViewController(memeVC, animated: true)
print("item tapped\(indexPath)")
}
}
errors
Use of unresolved identifier 'storyboard'; did you mean 'UIStoryboard'?
Add segue as mentioned in the image and select show
Set segue identifier in your storyboard as mentioned in the image
Add below Protocol:
protocol CollectionViewCellDelegate: class {
func userDidTap()
}
Add below property in your table view class where the collection view delegate returns.
weak var delegate: CollectionViewCellDelegate?
Update delegate method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate.userDidTap()
print("item tapped\(indexPath)")
}
}
confirm CollectionViewCellDelegate delegate to your first view controller & add this method:
func userDidTap() {
performSegue(withIdentifier: "showMemeViewController", sender: nil)
}
Add prepare for segue in your first VC.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMemeViewController" {
let memeVC: MemeViewController = segue.destination as! MemeViewController
memeVC.imagePassed = image
}
}
Please try this let me know if you faced any other issue. Thanks.
You're trying to access storyboard property in a tableview cell, which isn't there in the first place, it's a UIViewController property not a UITableViewCell property, hence the error, you'll have to delegate your selection to the viewController then let the controller do the segue normally.
You can start doing that via delegates as I mentioned above, for example if you're passing image to the controller you wanna segue to:
protocol ImageTableViewCellDelegate: class {
// pass the the image or any variable you want in the func params
func userDidTap(_ image: UIImage)
}
then you'd add it to the cell and confirm the controller to it
class SecondTableView {
weak var delegate: ImageTableViewCellDelegate?
}
In your controller:
extension MyViewController: ImageTableViewCellDelegate {
func userDidTap(_ image: UIImage){
let memeVC = storyboard?.instantiateViewController(withIdentifier: "MemeViewController") as! MemeViewController
memeVC.imagePassed = image
navigationController?.pushViewController(memeVC, animated: true)
print("item tapped\(indexPath)")
}
}
this should work, let me know if you had any further problems
I have View Controller A, which has five static collection view cells, with a title label, and a description label. Based on which cell was tapped, I need to segue to View Controller B, and View Controller B will present a list of products associated with that data.
I attempted to do this is didSelect method, but I think I am wrong... I realized after using print statements I am correctly getting the navigation to work, and I can also print the name label on View Controller A, but the data passed to View Controller B is nil.
View Controller A
var parameters: [Parameter] = [
Parameter(name: "Alkalinity", description: "A description here is about how important it is to have a stable measurement"),
Parameter(name: "Calcium", description: "A description here is about how important it is to have a stable measurement"),
// Cut the amount so I do not take too much space here
]
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = parameters[indexPath.row]
// Create an instance of DeatailViewController and pass that variable
let destinationVC = DetailViewController()
destinationVC.dataReceived = selectedCell.name
self.performSegue(withIdentifier: "segueID", sender: self)
}
View Controller B
only a print statement.
Expected: Pass the name of the cell I tapped to the second VC, (For now) but I want to show a list of products associated with each element in name label. ex: Alkalinity will show Alkalinity products ( should I define this in the same of different model)?
Error:
Showing nil on VCB
Suggestions:
Maybe using index path in didSelectRow?
When using a segue to pass data you need to implement prepareForSegue
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "segueID", sender:parameters[indexPath.row])
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueID" {
let vc = segue.destination as! DetailViewController
destinationVC.dataReceived = sender as! Model // Model is type of array parameters
}
}
but with vc instantiation DetailViewController() you need to use present/push
let destinationVC = DetailViewController()
destinationVC.dataReceived = selectedCell.name
self.present(destinationVC,animated:true)
For second way presenting DetailViewController() will crash the app as you don't load the vc from storyboard , so it should be like
let vc = self.storyboard!.instantiateViewController(withIdentifier: "DetailID") as! DetailViewController
If you are using segue, I would achieve that by doing something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueID" {
if let destinationVC = segue.destination as? DetailViewController {
destinationVC.dataReceived = selectedCell.name
}
}
}
I want to my collection View data (list.assets_id) want to parse DetailChannel
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
vedioId = id
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detailChannel"{
let destinationVC = segue.destination as! DetailsChannel
destinationVC.vedio_id = vedioId
}
}
In my DetailChannel ,
override func viewDidLoad() {
super.viewDidLoad()
debugPrint("DetailsChannel:::::\(vedio_id)")
if let stringVideo = vedio_id {
print(stringVideo)
}
}
but didn't work my project and didn't call func prepare().How to slove?
I guess you've added segue from CollectionViewCell to
DetailChannel. Delete that segue.
Now add a segue from your CollectionViewController (not CollectionViewCell) to DetailChannel. If you don't know how to add it, here is the process:
First control-drag from the CollectionViewController to
DetailChannel and let go. visualize
here
Then select the segue and name it something meaningful to you (in your case detailChannel).
visualize here
Now inside your collectionView(_:didSelectItemAt:) method add this line:
performSegue(withIdentifier: "detailChannel", sender: self)
I hope your prepare(for:sender:) is now being called.
My problem is I would like to Pass data from my collection view to a new view (tableview- but I think it's not necessary info)
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let myVC = DetailsTableViewController()
myVC.movieTitle = movies[indexPath.row].movieTitle!
print (movies[indexPath.row].movieTitle!)
performSegueWithIdentifier("DetailSegue", sender: reuseIdentifier)
}
Print is OK, but my movieTitle: String? will NIL on the DetailsViewController.
Help!
performSegueWithIdentifier will instantiate an appropriate destination controller and present it. The DetailsTableViewController you have instantiated here as myVC is never shown. You have a couple of options for how to approach this:
If you want to use segues then trigger the segue in didSelectItemAtIndexPath and implement prepareForSegue to pass data to the destination view controller (a destinationViewController will be available on the UIStoryboardSegue passed to that method).
Alternately you could avoid using segues and present your myVC directly by pushing it onto your current navigation controller (if one exists you could call self.navigationController.pushViewController(myVC, animated:true)), presenting it as a modal, or whatever makes sense in your app.
problem solved. thanks
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetailSegue" {
let detailsVC = segue.destinationViewController as! DetailsTableViewController
if let cell = sender as? UICollectionViewCell, indexPath = collectionView!.indexPathForCell(cell) {
// use indexPath
detailsVC.movieTitle = movies[indexPath.row].movieTitle!
}
}
}