Unwind Segue Not Working in page view controller, Have Checked Other Posts - ios

So I have a page view controller setup and each of my pages has a back button that calls an unwind segue which when arriving at the root page controller calls another unwind segue to get back to the main menu:
func backButtonAction(sender:AnyObject!){
println("ok")
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("unwindGameContentViewController", sender: self)
}
//self.performSegueWithIdentifier("loadFollowPatternViewController", sender: self)
//self.performSegueWithIdentifier("unwindGamesContentViewController", sender: self)
}
and
#IBAction func unwindToViewController(sender:UIStoryboardSegue){
println("blow")
self.performSegueWithIdentifier("unwindGamesViewController", sender: self)
}
On the first page clicking the back button functions as usual but then the second and third page of the view controllers do not function at all. The backButtonAction function is called and the ok is printed but the unwind does not take place and the blow print line is not printed either.
I get no errors or warnings about storyboard or anything else.
My code used to work before Xcode 6.3 came out with the updated swift language, however I am not sure whether I broke the code before then or the update broke it.

Related

IOS swift UIBarButtonItem action

I've a table view with navigation controller embedded in. I've added a UIBarButtonItem (add) button. When I click this button it opens a new view where user enters the data and submits it (which makes a web service call) and returns back to the previous view. This navigation happens as shown below,
func addTapped(_ sender:UIBarButtonItem) {
print("Called Add")
let vc = (storyboard?.instantiateViewController( withIdentifier: "newNote")) as! newNoteVC
self.navigationController?.pushViewController(vc, animated: true)
}
And in new view I do following,
#IBAction func saveButton(_ sender: UIButton) {
if (self.noteDescription.text?.isEmpty)! {
print("Enter missing note description")
return
} else {
let desc = self.noteDescription.text
self.uploadNote(noteText: desc!, noteDate: self.dateInMilliseconds)
self.navigationController?.popViewController(animated: true)
}
}
This way a record gets saved and a view gets popped from the navigation controller stack but only thing I don't how to do is refresh the table view data in the parent view (where I might need to make a new http service call to read all the records).
I hope I'm able to explain the issue? Any help is appreciated.
As mentioned in the comments, making a service call just to update the tableview might be a overkill. However, if this is the business scenario which needs to be implemented, you can do the same in
func viewWillAppear
in the parent view controller. You can make the service call in this method and reload the table view with the data.
You would also need to check the overall navigation of the application as making service calls in viewWillAppear method is not a good approach as these gets called everytime the view is shown. For Ex: If coming back from a navigated view then also the method is called.

How can I create two segues for a single button in a view controller?

I have a root view controller - which is a simple page presented to the user. In this page, there is a UIBarButton that goes to the user profile page.
When the user is in its profile, he/she'll have a back button that will allow him/her to go back to the root view controller.
However, the root view controller is different for admins and clients (there is one standard view controller for admins and one standard view controller for clients).
How can I create two segues that are triggered by the 'Back' profile button? I mean, depending on who is currently logged in (an admin or a client), I would like to go back to their respective pages.
The client cannot go back to the admin's page and neither vice versa.
Is there any way to create these two segues? Or even another/better way? I have tried to do that using storyboard, but when I create the second segue, it deletes the first one linked to the button.
You cannot do that but there is other way for that, create two segue bwtween SenderViewController and DestinatrionViewController. After that set action for your button and perform the segue according to your requirements.
#IBAction func buttonAction(_ sender: UIButton) {
if condition {
self.performSegue(withIdentifier: "identifier1", sender: nil)
}
else {
self.performSegue(withIdentifier: "identifier2", sender: nil)
}
}
Going off of Nirav D's answer, use an if...else with the condition that they are an admin or client. But don't control+drag from the button itself, control+drag from the ViewController as seen in the images below.
you should handle it in your code.
#IBAction func backClick() {
if isAdmin /* check condition here */ {
// admin work
} else {
// normal user work here
}
}
Then let create segue from storyboard and give it an identifier.
If you want perform segue, let use
performSegue(withIdentifier: "identifier", sender: nil)
if you want go back.
dismissViewControllerAnimated(true, completion: nil)
Hope it help.

xcode 8 swift: unwind segue transfer data is not working

So I have been trying to get a unwind segue to work from last two days. I have tried watching and follow several different tutorials and none was successful. I created the #IBAction override func unwind(for unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) but this never performs any of the code. I put a simple print and had it print text, it never printed the text. I created that in the first View Controller then in the second View Controller I had a button that I connected to the Exit at the top of the View Controller and selected the unwind action and it never unwinds. What am I doing wrong or missing?
So here is what I have so far I have 2 views: RaceViewController & SingleStatViewController
I will start by selecting specified rows in RaceViewController and they will open SingleStatViewController modally. I have a button in SingleStatViewController called dismissBtn. When I click the button it dismisses SingleStatViewContoller. I just need it to pass some data back to the RaceViewController.
So if the user selects 1 of 3 cells in the table (the rows are Half-Orc, Half-Elf and Human) it will open SingleStatViewController and ask to select 1 stat (these will be of 6 buttons (Str, Dex, Con, Int, Wis, Chr) when they select the one of the buttons it will return the data and update the detailTextLabel.
I select Human then I select Str. When it gets back to RaceViewController and it updates the text in the detailTextLabel to +2 Str.
Right now, this is the code I am using to dismiss. Can I use this to continue or do I actually need to perform the unwind:
#IBAction func dismissbtn(_ sender: Any)
{
dismiss(animated: true, completion: nil)
}
You need to perform unwind and send data as following:
#IBAction func unwindToRaceViewController(sender: UIStoryboardSegue)
{
if let sourceViewController = sender.sourceViewController
as? RaceViewController {
stat = sourceViewController.stat
}
You could refer to this article for unwind segues as alternative to delegate
You could also use delegates to pass data back to the previous controller.
Okay, so you have vc A and vc B, this is what you need to do to use unwind segue:
In vc A, create a segue function eg. #IBAction func unwind(segue: UIStoryboardSegue)
In vc B, write code that call self.performSegueWithIdentifier("unwind", sender: self) (assume that the identifier and the function name is the same - call this in your dismissbtn)
In vc B in storyboard, look on top of it, there will be an yellow button and 2 orange button, hold and drag the yellow button to the Exit orange button, choose the action that you created in vc A, give it an identifier as mentioned
In the unwind func, the rest is the same as normal segue when you pass data forward, just change destination to source and you must present vc B from vc A, else then use delegate

Segue is not working, and i can't figure out why

I have an if...then statement in the ViewDidLoad method for the view that acts as my storyboard entry point.
Basically, I am doing a check to see if there is any data in core data, to indicate that they've completed a small "setup form".
If it is found that the core data is empty or that the app has not been properly set up, I want it to automatically kick them over to the settings view with a segue.
My ViewDidLoad method looks like this:
override func viewDidLoad() {
super.viewDidLoad()
//Get any entries from the App Settings Entity
getAppSettings()
//If any entries are found, check to see if the setup has been completed
if (appSettings.count > 0) {
print("We found entries in the database for App Settings")
if (appSettings[0].setupComplete == false) {
print("Setup has not been completed")
self.performSegue(withIdentifier: "toAppSettings", sender: self)
} else {
print("Setup is completed")
//Load the settings into global variables
preferredRegion = appSettings[0].region!
usersName = appSettings[0].usersName!
}
} else {
print("We found no entries in the database for App Settings")
self.performSegue(withIdentifier: "toAppSettings", sender: self)
}
}
I made sure that the segue does exist, and that the identifier for the segue is exactly as I have it in the quotes (I even copied & pasted all instances of it to make sure that they are all consistent).
I also went the extra mile and put a checker in the "prepare for segue" method, to print whether it was getting called, and who the sender was:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("We're getting ready to segue!")
print(segue.identifier)
}
Both of those items get printed to the log, which tells me that the segue is being recognized and that the app is attempting to fire it. But - for some reason that I can't figure out - it simply isn't firing.
Any ideas what I am missing here?
I have an if...then statement in the ViewDidLoad
But that's the problem. viewDidLoad is way too early for this. Remember, all viewDidLoad means is that your view controller has a view. That's all it means. That view is not yet in the interface, and the view controller itself may not even be in the view hierarchy! It's just sitting out there in object space. You cannot segue from here; there is nothing to segue from.
Try waiting until viewDidAppear. If that makes it work, you might try moving it back to viewWillAppear, but I don't guarantee anything. Keep in mind that these methods can be called multiple times, so you might also need a flag to make sure that this segue fires just the once.

performSegueWithIdentifier has no segue with identifier

I encountered a crash while testing my app. The following image is my storyboard:
I have the code in View Controller:
#IBAction func unwindToHomeScreen(segue:UIStoryboardSegue) {
}
The view of "Add new Item" have a "Cancel" button, I controlled-drag it to the "Exit" icon at the top and link to unwindToHomeScreen, it works fine.
The "Add new Item" has a class AddTableViewController and the code I wrote inside:
#IBAction func save() {
// Execute the unwind segue and go back to the home screen
performSegueWithIdentifier("unwindToHomeScreen", sender: self)
}
I controlled-drag the "Save" button to the func, but the app crash when I click the button
I can use dismissViewControllerAnimated(true, completion: nil) instead, but I just wonder why performSegueWithIdentifier can't work?
I read the code at dropbox.com/s/hpybgg9x67rtqng/foodpinstatictable.zip?dl=0 and try to make one and using performSegueWithIdentifier like this example for practicing, I didn't see the segue identifier at her, what is the difference?
You haven't actually given that segue an identifier. unwindToHomeScreen is a function that you can call; what you're looking for is your segue identifier, which is set in Interface Builder like this:
In this example, I have a button wired to the next view via Interface Builder like you describe ("Interface Builder") and a button that is wired to this IBAction in my view controller ("Programmatically"):
#IBAction func goToNextView(sender: UIButton!) {
self.performSegueWithIdentifier:("go", sender: self)
}
In any case, what you're missing is the actual identifier, which can be set in the attributes of a segue created in Interface Builder.
Swift 4:
Sometimes we must clean the build folder and then try again.
Worked for me after ctrl-dragging the new segue and giving it a name, then using it programatically as:
performSegue(withIdentifier: "goToMyNewViewController" , sender: self)
I found that because I renamed my view controller, I needed to delete and recreate the segue.
A possible issue with iOS 12 and earlier (iOS 13 seems not to suffer from the same issue) might come from the fact that performSegue(withIdentifier:,sender:) is called from the view controller viewdidLoad() callback.
You absolutely must invoke it from the viewDidAppear(_ animated: Bool) callback in order to avoid the question-mentioned crash.
That will certainly save hours of hair-puling…
in my case reorder the Embed in
Tab bar controller
Navigation controller
vc (contains button - tapping button initiates a "show, e.g. push" segue)
Too fix the title in the navigationBar
I had the same issue.
All I did was:
I selected the segue indicator in the storyboard.
Deleted it.
Then created a new segue with the same identifier. Boom, it works.
I had it all wired up correctly. It was just that the viewController I was segueing from, was NOT instantiated from the storyboard. I had it instantiated pragmatically.
I initially had it written as:
let vc = DeviceVC()
Had to change it to:
let sb = UIStoryboard(name: "Main", bundle: Bundle(for: DeviceVC.self))
let vc = sb.instantiateViewController(identifier: "DeviceVC") as! DevieVC
for me --> click on the relation-arrow between view controllers and then select attribute inspector, there is identifier give name and select push class done...

Resources