How to pass a value to another ViewController by pushing in NavigationStack? - ios

This is my code.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0{
self.navigationController?.pushViewController(self.storyboard?.instantiateViewControllerWithIdentifier("History") as! History, animated: true)
TV.deselectRowAtIndexPath(indexPath, animated: false)
}
}
I push to another ViewController(named History) and I want to pass my value which is in this ViewController to History ViewController.
I know we can pass value by using segue and segue's destinationViewController and sourceViewController.
But there is no segue in this case.
So,I don't know how to assign a var's value to History's var.
Anybody can help me?

let history = self.storyboard?.instantiateViewControllerWithIdentifier("History") as! History
//Here U can Access the variable of History
history.yourVar=Assign Value
self.navigationController?.pushViewController(history, animated: true)
TV.deselectRowAtIndexPath(indexPath, animated: false)

Related

Passing Data Forward In Swift Without Segue

I'm currently making a to do list app using Swift 4. The home view controller has a tableview with some categories in it and when one is selected, it takes the user to a view controller where the items in that category are listed. I have a bug however as only the most recent item is showing in the list.
I think this is due to the way I am navigating to the list view controller. I am currently doing this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let destinationVC = ListVC()
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedCategory = categoryArray[indexPath.row]
}
navigationController?.pushViewController(destinationVC, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
}
And in the list view controller, I just have this to load the data:
var selectedCategory : Category? {
didSet {
loadItems()
}
}
I firstly created this app using storyboards and when using segues, it worked completely fine.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! TodoListVC
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedCategory = categoryArray[indexPath.row]
}
}
So basically, the problem is that in the secondary list view controller, it will only show the most recently added item and no other ones even when they are stored in core data. I think it is to do with the way I am showing the secondary view controller as I am creating a new object every time.
How to properly go to the next view controller?
Remove the segue and add the storyboard id
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "storyboard_id") as! TodoListVC
vc.selectedCategory = categoryArray[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
Try this it will help you:-
You can send data from one view controller to another using storyboard
instance.
let next = self.storyboard?.instantiateViewController(withIdentifier: "NextControllerStoryBoard_id")as! NextController
next.str = "data which you want to pass"
self.navigationController?.pushViewController(next, animated: true)
here NextController is your controller class name where you want to go.str is the string name which you declare on NextController like
let str = String()
you are able to send string in that variable in same way you send any thing array dictionary ,image, Int value etc.
NextControllerStoryBoard_id is id which you declare at storyboard of that controller
In storybard id add your storybard id
Hope this will help you
I think that with this chunk of code I already sensed that you are passing data to the other view controller the incorrect way:
let destinationVC = ListVC()
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedCategory = categoryArray[indexPath.row]
}
...
What I would suggest is that, instead of passing the data this way, you have to pass an array containing the items within the selected category using an array, then pass that array via the prepare for segue.
Then from the viewdidappear or viewdidload method in the receiving view controller, use the passed array from the source VC and use that as a datasource for your table view within that 2nd VC.

UICollectionView didSelectIotemAt issue

I have a UICollectionView that is populated by an array of images. I want to allow the user to tap on an image and preview it in a new UIViewController.
For some reason, didSelectItemAt method isn't working as expected. It doesn't throw an error, it gets called, just nothing happens really. Not sure what I do wrong here.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("did select item at was called")
let dashboardStoryboard = UIStoryboard(name: STORYBOARD_DASHBOARD, bundle:nil)
let destinationVC = dashboardStoryboard.instantiateViewController(withIdentifier: "PreviewPostImageVC") as! PreviewPostImageVC
destinationVC.selectedImage = arrayOfSelectedImages[indexPath.row]
self.navigationController?.pushViewController(destinationVC, animated: true)
}
I think Allen's comment points at the problem. If you're sure your method is being called (The print statement appears in the console) then the most likely problem is that self.navigationController is nil. With the optional chaining you're using, that call will fail silently if it's nil, which may or may not be what you want. Try changing it like this:
guard let navController = self.navigationController else {
print("Navigation Controller is nil!")
return
}
navController.pushViewController(destinationVC, animated: true)

Open specific viewController in tableView

I'm using a tableView like the iPhone's note application.
I can add/delete note (cells).
I'm facing a little issue when I delete a note.
Here's my code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true)
switch (indexPath as NSIndexPath).row {
case 0:
let Liste1 = self.storyboard!.instantiateViewController(withIdentifier: "liste1") as UIViewController
self.present(Liste1, animated: false, completion: nil)
case 1:
let Liste2 = self.storyboard!.instantiateViewController(withIdentifier: "liste2") as UIViewController
self.present(Liste2, animated: false, completion: nil)
case 2:
let Liste3 = self.storyboard!.instantiateViewController(withIdentifier: "liste3") as UIViewController
self.present(Liste3, animated: false, completion: nil)
default:
break
}
As you can see, each indexPath.row can open a counted ViewController.
If I have 3 notes and I delete the 2nd, the 3rd will open the 2nd viewController. Tell me if you don't understand..
I know the problem , I don't know if there are some solutions to open specific viewController .
I want Cells is linked to a viewController, not by the indexPath..
Thanks in advance !
The implementation here is wrong. How it should be is that a ViewController (say named DetailsViewController) should be pushed whenever the user selects a cell. Only the text associated text/note should change. The correct note should be fetched from an array of all the notes (with index being the indexPath.row of the selected cell) and then pass is to DetailsViewController while presenting it.
Deleting a note:
When the user deletes a note, just delete the not from this array of all notes.

pushViewController does no action

i have a tableview and i want to go to another vc when one of rows tapped. my didSelectRowAtIndexPath function is as below. print command works and shows the right clicked row. but when i use self.navigationController?.pushViewController it does not go to vc with playVideo storyBoardId. after changing it to presentViewController it works. what's wrong about my code that push doesn't work?
thanks
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked " + String(indexPath.row) )
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("playVideo") as! PlayVideoViewController
vc.id = self.video[indexPath.row].id
// Present View as Modal
//presentViewController(vc as UIViewController, animated: true, completion: nil)
// Push View
//self.navigationController?.pushViewController(vc, animated: true)
}
Its because the view controller you are currently in may not have a navigation controller.
You cannot push a view controller without having a UINavigationController.
If your requirement is to push a view controller, then perform the following steps.
Embed a navigation controller for the current view controller.(Open storyboard -> Choose your view controller -> Choose "Editor" -> "Embed in" -> UINavigationController)
Now your code
self.navigationController?.pushViewController(vc, animated: true)
will be working fine.
Make sure that your ViewController is indeed built on a NavigationController. Try forcing the line:
self.navigationController!.pushViewController
if it crashes, you know there is not nav set up. Or you could just check in your storyboard but this is a quick way to tell.
I dont know why are you doing it like this. I think its unnecessarily complicated.
This should by your function didSelectRowAtIndexPath:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("playVideo", sender: tableView)
}
Then you can specify as much segues as you want in this function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "playVideo") {
let indexPath:NSIndexPath = tableView.indexPathForSelectedRow!
let PlayVideoViewController = segue.destinationViewController as! PlayVideoViewController
//you can pass parameters like project id
detailVC.projectID = ids[indexPath.row]
}
}
Your segue has to be named like this in interface builder:

How to assign Two segues on a table cell in SWIFT?

I am totally new at IOS swift and working with android.
Here is my issue :
I'm developing a simple chatting App of IOS. I've already completed android ver and this is a kind of clone.
It has view controllers named VCList, VCMyFriends and VCChat. VCList is my very first view controller and has a table view. Touching a table view cell changes current view controller to VCMyFriends or VCChat.
When I touch a cell, app checks the member counts of the cell, so if it has other members then go to VCChat. If not, VCMyFriends on to invite my friends. Like following pic.
What I found is, I cannot assign two segues on a cell or split a segue with two ways. So I thought that can I change my VC without a segue? However I could not find any references or tutorial about it.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if( memberCnt == 0 ) {
self.presentViewController(VCMyFriends(), animated: true, completion: nil);
} else {
self.presentViewController(VCChat(), animated: true, completion: nil);
}
}
Above is my last try, and failed. It moves somewhere, but shows nothing at all. And if I can, I wish to use segues because have some datas to pass with segue.
Take care.
What I normally do is to create an instance of the controller via the instantiateViewControllerWithIdentifier and set the necessary member variables before calling presentViewController. You can also add a NavigationController if you want the capability the go back to the previous window.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let mainStoryBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if( memberCnt == 0 )
{
let vcMyFriends = mainStoryBoard.instantiateViewControllerWithIdentifier("VCMyFriend") as! VCMyFriends
vcMyFriends.membervar1 = membervar1
vcMyFriends.membervar2 = membervar2
self.presentViewController(vcMyFriends, animated: true, completion: nil)
}
else
{
let vcChat = mainStoryBoard.instantiateViewControllerWithIdentifier("VCChat") as! VCChat
vcChat.membervar1 = membervar1
vcChat.membervar2 = membervar2
self.presentViewController(vcChat, animated: true, completion: nil)
}
}
membervar and membervar2 are the data that you pass to the View Controllers. You need to set it before calling presentViewController so that they will be available when viewDidLoad is called.
Simply do this
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if( memberCnt == 0 ) {
performSegueWithIdentifier("VCMyFriends_segue", sender: self)
} else {
performSegueWithIdentifier("VCChat_segue", sender: self)
}
}
In your storyboard, select the first segue (the red line in your image) and choose Attributes inspector, then add VCMyFriends_segue as identifier.
Do the same thing for the second line (blue) and add VCChat_segue identifier.
Hope this helps

Resources