Swift 3: How to make sure that data is set before presenting in next view controller - ios

I am using prepare for segue to set a dictionary variable in another view controller. But the issue is the view controller opens the map without the data. How can I make sure I go to next view controller only after the dictionary variable data has been set.
Here is my code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMapSegue"
{
if let mapVC = segue.destination as? MapVC
{
if vendorStoreKeys.count != 0{
mapVC.vendorStore = vendorStoreKeys
}
}
}
}
But the vendor store array in next view controller is still empty when the controller is visible. It sets the data after some time but at that point I am unable to reload that view controller so I need to make sure I don't go to next view controller before the mapVC.vendorStore variable is properly set.

I was able to resolve the issue. Prepare for should have set the data before calling and it was. Issue was I actually forgot to remove the segue in the storyboard which was directly going from the button to the new view controller. So here is what I did
Removed the segue which was going directly from the collection view cell button to the next story board
Created a new segue from the top of the view controller to the next view controller
Named that segue "showMapSegue"
Build and Run. I got the data successfully in the next view controller. Hope it helps.

Related

Reload same View Controller but with different information

I have a Detail View Controller and I want to show the same Detail View Controller but with a different item.
var nexttype : Type!
let nexttypeVC = TypeDetailVC()
#IBAction func buttonTapped(_ sender: UITapGestureRecognizer) {
nexttype = type.Array![0]
nexttypeVC.type = next.type
self.navigationController?.pushViewController(nexttypeVC, animated: true)
}
When I print the name or a identifier of the item I get the correct one, but when I launch the simulator I get error. The values of the labels and everything is nil.
How can I tell the view controller to reload again but with a different item?
Call performSegue(withIdentifier:) rather than pushViewController. You'll need to programmatically register a segue or add one via storyboard. Then use prepare(for segue: sender:) to give the destination ViewController the item you wish. Note that the destination's viewDidLoad() is called after the prepareForSegue.
This is the standard Apple-recommended way to seed the destination ViewController with data it needs prior to its load.
Instead of pushing the same view controller onto the navigation stack. Try to arrange all the logic to update UI elements into a method. Call this method in viewDidLoad(). Calling self.viewDidLoad() is not a good idea.
Use observer pattern and call the method that updates UI elements.

How get values from ContainerView inside parent ViewController?

I have a view controller that use it as a login page.So I put login and cancel buttons and I want to use static table view for username and password fields. The problem is about static table view controller because I must put it inside a container view and have relation to it as a child view controller. I want to read text fields values when the user touches the login button.But because login button is inside parent view controller, I try to call exit segue to get values from text fields. But I can't do that and I don't know it's logical to do this action.
So in summary for this purpose is this way true or not and if true how can I do that?
You could do that by overriding prepare method.
1- From storyboard, give an identifier to the segue that embeds your login table view controller to the container, let's call it loginEmbedSegue.
2- Add a new property to the view controller that contains the container view like this:
var loginTableViewController: LoginTableViewController
3 - Inside the view controller that contains the container view, override prepare method in the following way:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loginEmbedSegue" {
self.loginTableViewController = segue.destination as! LoginTableViewController
}
}
4- Now, you have a reference to the the view controller that contains the username and password textfields.
Good luck!

UITableViews as pick lists

I have a view controller with 2 labels - each to be populated from lists in 2 separate table controllers. In my view controller I have 2 variables (temp and temp_1) to receive the data from the table controllers and populate the labels.
When I call the first table view and select an item that works fine and my first label is populated, when I then call the second table view that works too and my second label is populated - except that the first label is now blank - because temp is now blank.
I have attached my prepareForSegue from my first table view showing me passing my variable temp back to my view controller. (My second is similar and passes back temp_1)
Thanks for any help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "return_1" {
if let destination = segue.destinationViewController as? main_ViewController {
if let row = tableView.indexPathForSelectedRow?.row {
destination.temp = array1[row] as! String
}
}
}
}
My guess is that what you are saying in words is not what in fact you are actually doing. You say "back to my view controller", as if you were returning from the table view to the main view controller. That is what you want to do and what you should do, but it isn't what you're doing (I'm guessing). I think you've set up your storyboard with a normal segue from the table view to the main view controller. That doesn't go back; it makes a whole new main view controller. So of course the old label value is missing, because this is a different view controller from the one with the old label value (which effectively is still there, two layers down, covered up by this new instance).
What you want is an unwind segue. That is how you say "go back" in a storyboard.

View controller view getting misplaced when navigating back to the home screen of UITabbarController

I have a tabbarcontroller in my application and have added view controllers with the help of storyboard and segues,
When i am in the second tabbar item I have a table view embedded with a navigation controller filled with usernames and on top I have a hamburger icon, I select a particular item from the table list present in the hamburger icon and navigate to the details view controller I have used segues and given below is the code for the same
self.performSegueWithIdentifier("MY_DETAIL_SEGUE_NAME", sender: nil)
MY_DETAIL_SEGUE_NAME is actually a custom push segue of the SWRevealViewControllerSeguePushController, the push is working fine and i am able to navigate to the details screen.
The Problem: Since I am in the second tabbar item on the hit of back button i need to show the inital view / home view controller of the second tabbar item which is the friend view list, so on the back button i have written the below code in the detail screen
#IBAction func moveBackToController(sender: AnyObject) {
self.performSegueWithIdentifier("showFriendListPage", sender: nil)
}
showFriendListPage: This is a custom segue to the firendlist page using the SWRevealViewControllerSeguePushController and is pointed to the tabbarcontroller
To highlight the second tabbar item i have used the below code written in the detail screen
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
let objParentTabbar = segue.destinationViewController as! ParentTabbarController
if segue.identifier == "showFriendListPage" {
objParentTabbar.selectedIndex = 1
}
}
What happening here is when i navigate back to the home screen of the second tabbar item my view is distorted i.e. the UI elements are not placed in a correct order which they were when i first went to the second tabbar
Note: All my view controllers are embedded inside the navigation controller so the structure is
TabbarController----->NavigationController------>ViewController
Please suggest where I am going wrong and what needs to be done to resolve this, my only struggle is the view getting distorted and i dont really know why is this happening.
Call the view your controller via code in your application should do the trick
objParentTabbar.selectedViewController?.viewWillAppear(true)

Multiple unwind in the same button - Swift

I would like to know if it is possible to assign two different unwind method at the same button. For example:
I have this views navigations:
Home->A->B
Home->C->B
A and C views navigates to B, but then I want to return to previous views using the same B view and controller.
It is possible?
I have been thinking about write assign unwind method to the button programmatically depending what view comes.
Thanks in advance
I'm sorry about my english, is not good.
Here's a Swift solution that worked well for me. The code below only works if you hookup your segues correctly in the storyboard and in code. Checkout this page for great explanations on setting up unwind segues.
In summary:
You're accessing the same view from multiple other views. So, when you segue to a view, you can pass the source view controller (the view that you're currently in) to a property in the view that you're going to.
In your view that you will unwind out of, you can check the property holding the info (the class) on where you came from, and then perform a segue based on what view it is.
The code: (using ex: Home -> A -> B or... Home -> C -> B)
Note: B is the view that will unwind to multiple different views.
In A or C: (code works the same way in both views)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueIdentifierInViewAthatGoesToViewB" {
let controller:B = segue.destinationViewController as! B
//the code below passes our current view controller class to a property in view B.
//So, view B will know what view we came from.
//In our example, we're coming from view A or C
controller.viewControllerNavigatedFrom = segue.sourceViewController
}
}
In B:
//setup an IBAction that will check the source view controller (that we passed when we segued to this view) and perform a segue based on where we came from. You can hook this up to a button or anything you want really.
//isKindOfClass(A) - "A" would be the name of your class
//setup a property to receive the view controller class where we are coming from
var viewControllerNavigatedFrom:AnyObject?
#IBAction func myButtonPressed(sender: AnyObject) {
if self.viewControllerNavigatedFrom!.isKindOfClass(A) {
//Unwind to view A
performSegueWithIdentifier("unwindFromBbackToA", sender: sender)
}
else if self.viewControllerNavigatedFrom!.isKindOfClass(C) {
//Unwind to view C
performSegueWithIdentifier("unwindFromBbackToC", sender: sender)
}
}
Although, question isn't very clear. But what I could understand is that you want to navigate back to the previous view i.e. B>C or B>A depending upon where user came from.
If so, then check the UINavigationController. It keeps track of the navigation history and automatically adds a back button. Kind of like the back button in our browsers.
Here is a tutorial, although a bit old: Link

Resources