How to copy design from destination in UIStoryboardSegue animation? [duplicate] - ios

This question already has answers here:
Sharing an Image between two viewControllers during a transition animation
(2 answers)
Closed 5 years ago.
Lets say I have two UIViewControllers, we can call them ControllerOne and ControllerTwo.
In my app I have created a custom UIStoryboardSegue animation between ControllerOne and ControllerTwo. The effect I want to create with the animation is that it will feel like a part from ControllerTwo sliding onto ControllerOne so that the segue between the two UIViewControllers does not seems to be a segue.
From this point I don´t know which approach is the best one to take. The design for ControllerTwo is set through the storyboard but how do I get it?
(What I know is that I can´t copy the values from ControllerTwo into the segue because they have not been set yet so it will throw an error.)

Usually we Passing Data via this func prepareForSegue in the UIViewController class
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "idFirstSegue" {
let secondViewController = segue.destinationViewController as SecondViewController
//secondViewController.message = ...
}
}
You can also override perform func in the subclass of the UIStoryboardSegue class,
here is the code :
override func perform() {
var firstVC = self.sourceViewController as UIViewController!
var secondVC = self.destinationViewController as UIViewController!
//Then copy design from destination
}
The article fits you , I think.

Related

Do i have to use delegate when I want to change something from on VC in another VC ? SWIFT [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 5 years ago.
I am doing some excercises now. For example I create two view controllers in storybard and I want to change color for example from VC2 in VC1 by clicking button. In this situation delegate is needed or is other way to do it?
Normally, yes. But that depends . You can use NotificationCenter, you can use "prepare" function. The delegate is the most common option here. In your case:
protocol ChangeButtonColorDelegate {
func changeButtonColor()
}
class VC1 : ChangeButtonColorDelegate... {
func changeButtonColor() {
/* change button color here */
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "goto_vc2") {
(segue.dest as! VC2).delegate = self
}
}
}
class VC2 : ... {
var delegate : ChangeButtonColorDelegate!
}

How to perform segue from container view within a view displayed by navigation controller?

I want to segue from a view container within "H" that is presented using the navigation controller connected to the Split View Controller. How can I accomplish this? I have tried regular performSegueWithIdentifier using locally linked storyboard ID's but that removes the top navigation bar. I want to retain the top navigation bar and execute the segue as if it was done using the master navigation controller (rows that select which view controller is being presented in the detail view).
Any help is greatly appreciated!
Here is an example of how to perform a segue from an embedded ViewController.
ViewController.swift
import UIKit
protocol SegueHandler: class {
func segueToNext(identifier: String)
}
class ViewController: UIViewController, SegueHandler {
func segueToNext(identifier: String) {
self.performSegueWithIdentifier(identifier, sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EmbedH" {
let dvc = segue.destinationViewController as! HViewController
dvc.delegate = self
}
}
}
HViewController.swift
import UIKit
class HViewController: UIViewController {
weak var delegate: SegueHandler?
#IBAction func pressH(sender: UIButton) {
delegate?.segueToNext("GoToGreen")
}
}
Setup:
Use delegation to have the HViewController tell its embedding viewController to perform the segue.
Create a protocol called SegueHandler which just describes a class that implements the method segueToNext(identifier: String).
protocol SegueHandler: class {
func segueToNext(identifier: String)
}
Make your viewController implement this protocol by adding it to the class declaration line:
class ViewController: UIViewController, SegueHandler {
and by implementing the required function.
Add a delegate property to HViewController:
weak var delegate: SegueHandler?
Click on the embed segue arrow between ViewController and HViewController. Give it the identifier "EmbedH" in the Attributes Inspector.
Create a show segue between ViewController and the GreenViewController by Control dragging from the viewController icon at the top of ViewController to the GreenViewController. Name this segue "GoToGreen" in the Attributes Inspector.
In prepareForSegue for ViewController, when the "EmbedH" segue happens, set the delegate property of HViewController to self (ViewController).
When the user clicks the H button in the HViewController, call delegate?.segueToNext("GoToGreen") to trigger the segue in ViewController.
Here it is running in the simulator:
I was needing exactly what #vacawama proposed here, though I couldn't reproduce that, I tried exactly your steps but self.delegate?.segueToNext("GoToGreen") got called but neither the protocol itself nor the container view controller. After an entire day searching about this approach I realized the problem was with the swift version. Just replace this:
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EmbedH" {
let dvc = segue.destination as! HViewController
dvc.delegate = self
}
}
for this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EmbedH" {
let dvc = segue.destination as! HViewController
dvc.delegate = self
}
}
Other detail I was missing was about the embedded segue. Be sure to connect the container View to the HViewController, not the View Controller itself, otherwise the Embed option for segue won't appear.

iOS Swift - Presenting View Controllers and passing info between them [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I'm studying for the iOS Developer Nanodegree from Udacity and I can't figure out how to pass information between view controllers.
In this video, the instructor ask that we present view controllers using code, segue & code, and segue.
https://www.youtube.com/watch?v=zGzu5PcP8TI
I spent hours trying to understand this but I'm not getting anywhere. Is there any resources that clearly explains this?
Let's say you have VC1 and VC2 (two UIViewController classes) and that they are both in the same Storyboard file.
VC1 and VC2 both have a property:
var aProperty: String
VC1 has a UITextField, and when it changes, you set aProperty to the text field's text.
Now, you want to show VC2 and VC2 needs the value of aProperty from VC1.
If you set up a segue from VC1 to VC2, when it is triggered, this function in VC1 will be called (if it exists)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// You can set up VC2 here
}
For example:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let vc2 = sender as? VC2 {
vc2.aProperty = vc1.aProperty
}
}

How to identify the kind of StoryboardSegue

In my iOS project I use two kinds of UIStoryboardSegue, which present a view either within a navigation controller or as a modal view. I set the kind property in Interface Builder to:
Show (e.g. Push)
Present Modally
Now I want to be able to programmatically identify the kind of segue in order to customise the appearance of my ViewController. Like so:
class ViewController : UIViewController {
var isModal : Bool = false
...
}
class OtherViewController : ViewController {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.destinationViewController is ViewController {
let vc = segue.destinationViewController as! ViewController
vc.isModal = TODO
}
}
}
I was hoping there would be a property, but I can't find it. I was also hoping that the segue class would differ, but I also can't find enough documentation.
I originally stumbled upon this problem trying to use the isModal in order to alternate between dismissing the ViewController vs. popping the ViewController. I have noticed that there now seems to be a better alternative, which is the UnwindSegue. However, I still need the flag in order to customise appearance..
Thanks
Maybe I'm totally wrong but can't you use the identifier of the segue?
For example name all modal view controllers with Modal<Name>. Then check
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier.hasPrefix("Modal") {
let vc = segue.destinationViewController as! ViewController
vc.isModal = TODO
}
}

Modifing one variable from another view controller swift

I am developing an app in Swift that, in gist, tells people the price of Bitcoin in various currencies. To select the currency, the user chooses from a list in a view controller with a UITableView. This is currencyViewController, and it is presented from my main screen, viewController.
What I want to happen is that, when the user dismisses currencyViewController, it passes a string to a UIButton in the main viewController.
Here's the prepareForSegue function that should pass the data:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "presentCurrency") {
currencySelector.setTitle("\currencySelected", forState: UIControlState.Normal)
}
}
CurrencySelector is a UIButton in the main viewController, and currencySelected is a variable in the second view controller, currencyViewController.
It gives the error "Invalid Escape Sequence In Literal"
So, I've narrowed it down to one of two issues:
The variables from viewController can't be "seen" from currencyViewController. If so, how can I modify the text of CurrencySelector from CurrencyViewController?
For some reason, when the user exits the pushed CurrencyViewControler, prepareForSegue isn't called.
What is going on here? Thanks, and apologies - I am but a swift newbie.
2 - "prepareForSegue" is called when you push a new view controller via the segue, but not when you dismiss it. No segue is called upon dismissal.
1 - A good way to do this would be the delegate pattern.
So the main view controller would be the delegate for the currencyViewController, and would receive a message when that controller is dismissed.
In the start of the currencyViewController file you prepare the delegate:
protocol CurrencyViewControllerDelegate {
func currencyViewControllerDidSelect(value: String)
}
and you add a variable to the currencyViewController:
var delegate : CurrencyViewControllerDelegate?
Now, the mainViewController has to conform to that protocol and answer to that function:
class MainViewController : UIViewController, CurrencyViewControllerDelegate {
//...
func currencyViewControllerDidSelect(value: String) {
//do your stuff here
}
}
And everything is prepared. Last steps, in prepareForSegue (MainViewController), you will set the delegate of the currencyViewController:
var currencyVC = segue.destinationViewController as CurrencyViewController
currencyVC.delegate = self;
And when the user selects the value in currencyViewController, just call that function in the delegate:
self.delegate?.currencyViewControllerDidSelect("stuff")
A bit complex maybe, but it's a very useful pattern :) here is a nice tutorial with more info if you want it:
http://www.raywenderlich.com/75289/swift-tutorial-part-3-tuples-protocols-delegates-table-views
You have to use the parantheses to eval variables in strings, i.e. println("\(currencySelected)")
To access variables in the second view controller (the one which is the destination of the segue) you have to get a reference to it:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "presentCurrency") {
let currencyViewController = segue.destinationViewController as CurrencyViewController // the name or your class here
currencySelector.setTitle("\(currencyViewController.currencySelected)", forState: UIControlState.Normal)
}
}

Resources