Is there any way to assign a segue as well as an IBAction to a button? Also would there be a different method of attempting this of transitioning from an MPMediaPickerController (e.i, the user would be on one view controller, choose a song, and appear in another)
The easiest way of doing that would be to place the segue into the IBAction. That way it will run both. To keep your code clean you could create a separate method for the segue and then call that method from inside the IBAction.
Example
#IBAction func buttonPressed(sender: UIButton) {
segue()
//do stuff
}
func segue() {
//run the transition
}
Hope that helps :)
Related
I'm trying to segue into a 'settings' View Controller by clicking a button, and I'm assembling it via code but don't know what I'm doing wrong.
This is my button code:
#IBAction func settingsButton(_ sender: UIButton) {
self.performSegue(withIdentifier: "SettingsViewController", sender: self)
}
The View Controller is called 'Settings View Controller' (unsurprisingly). The app crashes whenever I press on it in my Simulator.
It'll probably be a simple thing, but any ideas what I'm doing wrong?
You must set your segue identifier whatever you want (for your question = SettingsViewController) from storyboard :
Hope it helps...
I am looking to build an app with two view controllers (VC1 and VC2) that each contain a timer. I would like for my user to be able to switch back and forth between these views and allow each timer to still run.
Currently, I have been successful in unwinding to either VC1 or VC2 (depending on which I set as the initial view controller), though I am having difficulty in successfully unwinding back and forth (i.e. from VC1 to VC2 back to VC1 and etc.)
I figured I might be able to accomplish this by initially segueing from VC1 to VC2 with a normal segue (from a button press), and though it will unwind back to VC1, I cannot get my app to unwind back to VC2 from here.
My two simple timer view controllers
Here is the code (for VC1):
#IBAction func unwindToSecondView(_ sender: UISwipeGestureRecognizer)
{
performSegue(withIdentifier: "unwindToSecond", sender: self)
}
#IBAction func backFromSecondView(segue: UIStoryboardSegue) {
}
And for VC2:
#IBAction func segueToFirstView(_ sender: UISwipeGestureRecognizer)
{
performSegue(withIdentifier: "unwindToFirst", sender: self)
}
#IBAction func backFromFirstView(segue: UIStoryboardSegue) {
}
I am really new to swift, and have found a couple interesting sources on here (How to unwind two view controllers and Swift Timer() will not update label after switching between views) but have not had much success otherwise -- would really appreciate any advice or ideas for different implementations. Thanks!!
Apple has published good example for that. I recommend always check Apple Developer Guide sites and source code. Your answer below. https://developer.apple.com/library/content/samplecode/SegueCatalog/Introduction/Intro.html
I found this tutorial useful.
working-with-unwind-segues-programmatically-in-swift
segue from A-B and from B-A you can just dismiss() and if you want to send data back from B-A you can create a delegate.
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.
I have a navigation tableview controller Calculator and that goes to AddActiveIngredients which is where I add everything in for the calculator.
I have the segue method backButton in Calculator and in AddActiveIngredients I have click dragged the segue from the controller to exit and selected the segue in the Calculator class.
The segue identifier is also backButton but it's not doing anything.
I've tried this code to try and trigger the segue manually but that's not working. Am I missing something so simple?
override func didMoveToParentViewController(parent: UIViewController?) {
if (!(parent?.isEqual(self.parentViewController) ?? false)) {
print("Back Button Pressed!")
self.performSegueWithIdentifier("backButton", sender: self)
}
}
It sounds like you just want to remove the AddActiveIngredients from the stack. If so, you just need to call a function to dismiss it.
func dismissVC() {
dismissViewControllerAnimated(true, completion: nil)
}
You can put that in a button tap or something else. It'll work with Show and Modal segues. Unwinding may be overkill for what you're doing.
Hope it helps!
To use the Exit icon you need not create a segue at all.
All you have to do is add a method in the ViewController to which you want to unwind to and add a method with the signature:
#IBAction func myUnwindAction(segue: UIStoryboardSegue) {
// do stuff
}
Remember, you have to add this method in the target ViewController
When you Control-Drag from a button to the Exit icon, this method will now show up.
When you now click the button, the current ViewController will be popped and the action method in the target will be called.
Hope this helps.
with Swift 5 you can use Dismiss function
#IBAction func dismissViewController(_ sender: Any) {
//Go back to previous controller
dismiss(animated: true, completion: nil)
}
I have two view controllers. On view controller1 I have the following:
a segue that takes me to viewcontroller2 - this segue is named "showme" and is attached to the viewcontroller
an IBAction for a UIButton
In my code I have the following for the button press action
#IBAction func buttonPress(sender: AnyObject) {
println("button pressed")
performSegueWithIdentifier("showme", sender: self)
}
I also have the following method:
override func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool {
println("Should performing....")
return true
}
For some reason the shouldPerformSegueWithIdentifier function is never called. If however, I add the segue directly on the UIButton to ViewController2 it is.
I have confirmed that calling it direction within my button action works (see below), but this is not what I understand to be the way it works. The same is true for prepareforSegue..
#IBAction func buttonPress(sender: AnyObject) {
println("button pressed")
if (shouldPerformSegueWithIdentifier("showme", sender: self)){
performSegueWithIdentifier("showme", sender: self)}
}
This behaviour is perfectly natural, for the following reasons:
1) shouldPerformSegueWithIdentifier is used to make sure that a segue that has been set up in Storyboards should be triggered, so it only gets called in the case of Storyboard Segues and gives you the chance to not actually perform the segue.
2) When you call performSegueWithIdentifier yourself, shouldPerformSegueWithIdentifier is not called because it can be assumed that you know what you are doing. There would be no point in calling performSegueWithIdentifier but then return a NO from shouldPerformSegueWithIdentifier.
#nburk answer is absolutely correct.
However I understand that in some situations it could be useful if shouldPerformSegueWithIdentifier:sender: would be called anyway, also when a call to performSegueWithIdentifier:sender: is made in code.
For instance we want to make some validations to decide whether performing a segue or not and we want to keep this logic in a single place and not duplicating all over the place conditions like the following:
if (self.shouldPerformSegue) {
[self performSegueWithIdentifier:identifier sender:sender];
}
This can be easily achieved overriding performSegueWithIdentifier:sender: as follows:
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([self shouldPerformSegueWithIdentifier:identifier sender:sender]) {
[super performSegueWithIdentifier:identifier sender:sender];
}
// otherwise do nothing
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
return self.shouldPerformSegue;
}
This way you can use shouldPerformSegueWithIdentifier:sender: to define your logic to allow/deny both IB and code triggered segues.
As the answer above. If you call performSegueWithIdentifier then shouldPerformSegueWithIdentifier is not called.
As an example:
Lets say you have an embedded segue inside a container view in order to show some images that you can swipe through. And embedded segues gets fired right away when you VC has loaded. But if you would have to download the images from an remote API your app would crash since there wouldnt be any images to display in the embedded segue/container view.
In this case shouldPerformSegueWithIdentifier would be needed.
You could setup a boolean value that you check in shouldPerformSegueWithIdentifier if its false return false and your segue wont be fired. And once your app has downloaded the images you could call performSegueWithIdentifier
Thanks #tanzolone for the perfect solution. Rewrote code on Swift 5.
To forcefully call shouldPerformSegue before performingSegue, you can override performingSegue in you class:
override func performSegue(withIdentifier identifier: String, sender: Any?) {
if shouldPerformSegue(withIdentifier: identifier, sender: sender) {
super.performSegue(withIdentifier: identifier, sender: sender)
}
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
// Your code (return true if you want to perform the segue)
}
if you're using this code you need to remove;
[self performSegueWithIdentifier:name sender:sender];