I have a registration view controller. In it I process the input provided by the user soon as he clicks on the register button. This button in the view is connected to an IBAction where I validate the input provided.
How is t possible to trigger the segue and pass the data within the IBAction (not override prepareforsegue) to the next view controller? If the validation fails it shouldn't attempt to execute segue but rather stay on same view to display validation errors.
Thanks for support. The question has been asked in different ways before surely but I wasn't able to find a good combine of segue in ibaction and passing data too.
You can create a segue from one view controller to another and can put a check in your button's IBAction, like this:
if (validationPasses)
{
self.performSegueWithIdentifier("segueIdentifier", sender: self)
}
And if you don't won't to override your prepareforsegue, you can pass the data using delegates.
However, by overriding prepareforsegue, you can pass data to your next view controller like this:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "segueIdentifier") {
// pass data to next view controller
let vc : NextViewController = segue!.destinationViewController as NextViewController
vc.someVariable = someValue
}
}
Here NextViewController is your next viewcontroller, change its name to your next view controller and in this view controller define variable to whom you want to pass value, in this case it is someVariable
Related
I have two view controllers, the first one has two buttons, signup and login, the second VC does the function of signup and login stuff (I wrote functions to switch between signup and login mode), is it possible to identify if user pressed login/signup button in the first VC so the right function will be called in the second VC when performing segue?
You have tell the second view controller what to do upon the first view controller selected option (signin or signup). I would assume that you could do this by simply declaring a flag and send it to the second view controller, for instance:
Declare a boolean variable in your second view controller (let's say shouldBehavesAsLogin) which means if selection is login it should be true:
// Controller that could represents signin or signup:
class SecondViewController: UIViewController {
//...
var shouldBehavesAsLogin = false
// ...
}
thus you could determine what is the value that should be assigned to it based on which button tapped, first view controller:
class FirstViewController: UIViewController {
// ...
private var isLoginTapped = false
#IBAction func signinTapped(sender: UIButton) {
isLoginTapped = true
}
#IBAction func signupTapped(sender: UIButton) {
// nothing to do here, isLoginTapped is false by default...
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MySegue"{
if let nextViewController = segue.destination as? SecondViewController {
nextViewController.shouldBehavesAsLogin = isLoginTapped
}
}
}
// ...
}
Thus all you have to do is to check the value of shouldBehavesAsLogin whether is it true to let the controller behaves as login or false to do the opposite.
Additional Tip:
If the purpose of adding IBActions for each button is just navigating to the second view controller, I would suggest to let both of the buttons to have the same IBAction, but you should let the sender to be of type UIButton instead of Any, thus you could do -for instance-:
#IBAction func aButtonTapped(sender: UIButton) {
// do the default behvior for both signin and signup (navigate to the second controller)
// signinButton is the button you tap for navigating to second controller to behaves as signin
isLoginTapped = sender === signinButton ? true : false
}
This answer assumes there is only one segue between the two view controllers. If there is more than one, you can simply use the segue identifier in prepareForSegue.
I'd handle this by using the sender parameter on either -prepare(for segue:sender:) or -performSegue(withIdentifier:sender), depending on whether you are triggering the segue directly from the button or in code.
If the buttons are triggering the segue, you can test whether the sender params is one of the two buttons concerned, and perform appropriate setup on the destination VC. If the segue is being triggered in code in an IBAction method, you could either pass through the button reference from the IBActions sender parameter, or pass some other identifying object that your prepareForSegue method is able to deal with.
Bear in mind that the target VC's views will not have loaded when prepareForSegue is called, so you may need to set some state on the target VC (e.g. a login/signup enum property) which is then used to set up the VC appropriately when its -viewDidLoad is called.
I have a searchViewController where I search for users and UITableView gets updated dynamically with user information. The cell for the UITableView is custom - it has a UIImage, the usernameLabel, and a button called "Add".
What I want is that if the user clicks on the add button of the cell, it should pass the user information on that cell (image and username) to another view controller that has a UITableView that is a friend list.
However, so far the only way I know is by using performSegue to pass the data on to the other viewController holding the friendlist UITable. But by this method, every time I click the add button it segues to the other view controller which I don't want. I want it to stay on the searchViewController when the add button is clicked - I only want the data to be passed.
Is there any way I can do this? Is using NSUserDefaults advisable for passing data of this sort?
For simplicity I will use FriendListVC and AddVC
If you are going to your AddVC from FriendListVC via a bar button item or something and your stack looks like:-
FriendListVC -> AddVC
There are two approaches you can use:-
1) Create a delegate of your friendListVC in your addVC and modify the friendListVC datasource on any changes there
2) Or, and I recommend this approach, just reload your FriendListVC datasource on it's viewWillAppear. viewWillAppear will get called even if you navigate back. Thus even if you add a deleteVC in the future and navigate back, the viewWillAppear will perform the updates and it will be independent of any other VC
Hope that helps
Use delegate for passing data between view controllers. you can find this useful
Passing data between 2 UIViewController using delegate and protocol
you can use NSUserDefaults but delegate pattern is better than this.
You can use callback method best and easy way to pass data one controller to another
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let viewControllerB = segue.destinationViewController as! ViewControllerB
viewControllerB.callback = { message in
//Do what you want in here!
}
}
In ViewControllerB:
var callback : (String -> Void)?
#IBAction func search(sender: AnyObject) {
callback?("Pass data to view controller1")
self.dismissViewControllerAnimated(true, completion: nil)
}
The easiest way to do this is by making an instance of the view controller that you want to pass data to, in the current view controller. I will write you a sample code for this.
class yourTableViewController: UITableViewController {
var controllerToPassData: UIViewController()
func clickTableButton(sender: UIButton) {
controllerToPassData.count += 1
}
}
class controllerwhereDataisPassed: UIViewController {
var count: Int!
}
Pick the instance of the controller where you want to pass data to from the navigationController stack and use this code.
Here's what I'm trying to do:
I have 2 views, Settings and Main Screen.
I've coded a segue to occur when a button in Settings is pressed, taking the view to the Main Screen. The identifier is "reset".
I'm trying to have the Main Screen perform a series of actions if this segue is triggered, but I can't find the function or way to do this.
Any help on how to implement this? I'd like it to trigger when the segue occurs.
You can pass arguments to the main screen in the prepareForSegue function in the settings page. Then in your main screen you can put in checks in your viewWillAppear function to handle them as you see fit.
Example:
In Settings:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "reset") {
// pass data to next view
let viewController:ViewController = segue!.destinationViewController as MainViewController
viewController.settings = settings // where settings is what you want to pass
}
}
In Main Screen:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if self.settings { // Do something }
}
If you're wanting something to happen when the segued view controller is triggered you can do it in a couple of places.
If you want the event to happen at the time the segue is fired, perform your code inside of prepareForSegue. There you can check the UIStoryboardSegue object's identifier field for "reset" and if true, call your logic.
If you want it to happen when the destination view controller loads or appears, do it inside of its viewDidLoad or viewDidAppear methods. In your case those methods would exist on the "Main Screen" view controller class.
Currently developing a small ios app in swift, I have populated a collection view cell with data from a .plist, each cell has a title and button, what i'm wanting is to segue to multiple view controllers in the storyboard depending on the segue identity once the button is pressed. For example if the segue has the id set as food, i want it to navigate to the view called food?
or if it is easier for the segue to pull the title from the cell then navigate to the view with the same title as the cell?
ill try and explain in code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "food"
{
//then navigate to the view controller called food
}
else if segue.identifier == "drink"{
{
//navigate to the view called drink
}
}
If food, drink or any other items have their own unique view in storyboard this is achievable.
You can assign a string to each button in UICollectionView and check which item in the collection was tapped and do a performSegueWithIdentifier: with button string.
performSegueWithIdentifier("toComments", sender: self)
Then prepareForSegue: method to pass data. Do another if for drink.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toFood" {
let ExchangeViewData = segue.destinationViewController as! FoodViewController
ExchangeViewData.foodMenuToShow = foodMenuID //This can be anything that you get your food items.
}
}
You can't do what you are asking for. A segue identifier is what determines which view controller gets invoked by the segue. If you want to go to a different view controller, invoke a segue with a different identifier. By the time you get to prepareForSegue it's too late. The segue to a specific view controller is already in progress.
You should explain what it is you're trying to do and we can help you solve your problem rather than trying to fight the APIs and do something that's neither possible nor appropriate. (Your question is an example of an "XY problem".)
I have two UICollectionViewControllers and the first one uses a push segue to get to the second one. The problem I'm having is passing information back to the first controller when the back button (the one that gets added automagically) is pressed in the second controller. I've tried using the segueForUnwindingToViewController, and canPerformUnwindSegueAction override functions, but no dice. I need to be able to access both view controllers so I can set some variables. Any ideas?
Here is an example with two view controllers. Let's say that the names of the two view controllers and ViewController and SecondViewController. Let's also say that there is an unwind segue from the SecondViewController to the ViewController. We will pass data from the SecondViewController to the ViewController. First, let's set the identifier of this segue by opening the document outline and selecting the unwind segue. Then open up the attributes inspector and set the identifier to "unwind".
SecondViewController Code:
class SecondViewController: UIViewController
{
override func prepareForSegue(segue: UIStoryBoardSegue, sender: AnyObject?) {
if let identifier = segue.identifier {
if let destination = segue.destinationViewController as? ViewController {
if identifier == "unwind" {
destination.string = "We Just Passed Data"
}
}
}
}
}
ViewController Code:
class ViewController: UIViewController {
var string = "The String That Will Be We Just Passed Data"
#IBAction func unwindSegue(segue: UIStoryBoardSegue) {
}
}
It sounds like you are trying to intercept the back button, there are many posts for this on SO, here are two:
Setting action for back button in navigation controller
Trying to handle "back" navigation button action in iOS
In practice, it is more clear to return state in closures (more modern), or delegates.