swift delegate beetween two view controller without segue
Typically you set a new view controller's delegate property in prepareForSegue:
. You said you're not using a segue, so you'll need to instantiate the second view controller and present it somehow. You can do this by doing something like:
let storyboard = UIStoryboard(name: "AStoryboardName", bundle: nil)
let secondVC = storyboard.instantiateViewControllerWithIdentifier(anIdentifier) as! targetViewController
secondVC.delegate = self
presentViewController(secondVC, animated: true, completion: nil)
You have a testDelegate()
method in both view controllers, but you only want it in the first view controller. Then your second view controller can call delegate?.testDelegate()
at the appropriate time.
Finally, you typically want to make delegate properties weak, so I would recommend changing var delegate : testProtocol?
to weak var delegate: testProtocol?
I would read up on delegation. Here is a relatively simple 5 step process to delegation that may help you:
Delegation in 5 Steps:
object A is the delegate for object B, and object B will send out the messages:
- Define a delegate protocol for object B.
- Give object B an optional delegate variable. This variable should be weak.
- Make object B send messages to its delegate when something interesting happens, such as the user pressing the Cancel or Done buttons, or when it needs a piece of information.
- Make object A conform to the delegate protocol. It should put the name of the protocol in its class line and implement the methods from the protocol.
- Tell object B that object A is now its delegate (in prepareForSegue(sender)).
Swift delegate beetween two VC without segue
You need to create one more protocol in your SecondViewController
to Pass that delegate from ThirdViewController
to FirstViewController
.
FirstViewController:
import UIKit
class ViewController: UIViewController, DataSentDelegate, dataSentDelegate {
@IBOutlet weak var imagefromThirdVC: UIImageView!
var thirdVCImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func buttonTapped(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
vc.delegate = self
self.navigationController?.pushViewController(vc, animated: true)
}
func goToThirdVC() {
let vc = storyboard?.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
vc.delegate = self
self.navigationController?.pushViewController(vc, animated: true)
}
func recievePhoto(data: UIImage) {
thirdVCImage = data
imagefromThirdVC.image = thirdVCImage
}
}
SecondViewController:
import UIKit
protocol dataSentDelegate {
func goToThirdVC()
}
class ViewController2: UIViewController {
@IBOutlet weak var passingImage: UIImageView!
var delegate: dataSentDelegate? = nil
var images: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
images = UIImage(named: "screen")
}
@IBAction func actionButton(_ sender: Any) {
self.delegate?.goToThirdVC()
}
}
ThirdViewController:
import UIKit
protocol DataSentDelegate {
func recievePhoto(data: UIImage)
}
class ViewController3: UIViewController {
var delegate: DataSentDelegate? = nil
@IBOutlet weak var passedImageView: UIImageView!
var passedImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
passedImage = UIImage(named: "screen")
passedImageView.image = passedImage
}
@IBAction func action(_ sender: Any) {
let data = passedImageView.image
delegate?.recievePhoto(data: data!)
// delegate?.goToFirstVC()
guard let viewControllers = self.navigationController?.viewControllers else {
return
}
for firstViewController in viewControllers {
if firstViewController is ViewController {
self.navigationController?.popToViewController(firstViewController, animated: true)
break
}
}
}
}
Delegation between two ViewControllers without segues
You are assigning your delegate to secondVC
but the view controller that is actually being presented is in secondStoryboard
, so you should set the colorDelegate
property of secondStoryboard
.
Assign Delegate Without Segue or Programatic Call
Well if you want to continue using the delegation pattern, you'll need to update the VC2 to pass throw the delegate callbacks.
So using the code from that example you posted:
ViewControllerOne:
class ViewControllerOne: UIViewController,testProtocol {
@IBAction func btInit(sender: AnyObject) {
println("Bt Init")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController2: ViewControllerTwo = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as ViewControllerTwo
viewController2.viewController1 = self
self.presentViewController(initViewController,animated: false, nil)
}
func testDelegate(){
println(" in my view controller delegate ")
}
}
ViewControllerTwo:
class ViewControllerTwo: UIViewController,testProtocol {
var viewController1: ViewControllerOne? = ViewControllerOne()
@IBAction func btInit(sender: AnyObject) {
println("Bt Init")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController3: ViewControllerThree = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as ViewControllerThree
viewController3.delegate = viewController1
self.presentViewController(initViewController,animated: false, nil)
}
}
ViewControllerThree:
protocol testProtocol {
func testDelegate() // this function the first controllers
}
class ViewControllerThree: UIViewController {
@IBAction func BtTarget(sender: AnyObject) {
println("bt target pressed")
delegate?.testDelegate()
}
var delegate : testProtocol?
}
A Better Option
Personally, I don't like this approach because it adds an unnecessary coupling on ViewControllerTwo
from the other two VCs that need to communicate, so IMO a better alternate is to use the Observer pattern through use of NSNotification
such that VC1 registers as a listener for a notification, and then at some later point, VC3 posts the notification (and optionally whatever data), VC1 receives it and does whatever it needs to.
Passing Data between View Controllers without segue
If its a small data like some string or variable you can use UserDefault or pass data using that class variable like vc2.data = data
How to use UserDefaults How to use UserDefaults in swift?
If its more like table or number of user list you can use plist store in your bundle at can retrieve from any view controller
using Plist How do I get a plist as a Dictionary in Swift?
if two controller are some how connected you can use delegates.
delegats:- Delegates in swift?
You can also use notifications if you are not sure when data will be available/ or send base on some action, or send if something is trigged.
Pass data using Notifications How to pass data using NotificationCentre in swift 3.0 and NSNotificationCenter in swift 2.0?
Passing Data with without Segue from Container View to MainVC
Delegate
pattern should help you. First of all you need the delegate protocol:
protocol SelectSoundVCDelegate {
func didSelectTrackNumber(_ trackNumber: Int)
}
with func that accept the trackNumber
value. Next, you need to create delegate
property in SelectSoundVC
:
class SelectSoundVC: UIViewController {
weak var delegate: SelectSoundVCDelegate?
var trackNumber: Int!
@IBAction func winterSoundBut(_ sender: UIButton) {
trackNumber = 1
delegate?.didSelectTrackNumber(trackNumber)
}
}
that will be call the didSelectTrackNumber
in @IBAction
. Note that delegate
property should be weak to avoid reference cycles. The last step, in MainVC
you should set delegate
property of SelectSoundVC
:
selectSoundVC.delegate = self
This part is little bit tricky, because you need the instance of SelectSoundVC
to set the delegate. You can set it in prepareFoSegue
method, for example:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewController = segue.destination as? SelectSoundVC, segue.identifier == "SelectSoundVC" {
viewController.delegate = self
}
}
Go to second viewController without segues
- secondVC.delegate = self
This line of coding is passing object reference of current class in which you are standing to SecondViewController. Now, you can call methods of firstViewController(I assume this name), by using delegate object in secondViewController.
- This delegate is not needed
, if you simply want to go to Next Screen which is SecondViewController in your case.
- Helpful code:
Following will pass you to next controller, make sure that you have navigationController or not. As in NavigationController, you have to pushViewController into stack.
@IBAction func goToView(sender: AnyObject) {
let secondVC= storyboard?.instantiateViewControllerWithIdentifier("secondViewController") as! SecondViewController
self.presentViewController(secondVC, animated:true, completion:nil)
}
or in case of NavigationController
@IBAction func goToView(sender: AnyObject) {
let secondVC = self.storyboard?.instantiateViewControllerWithIdentifier("secondViewController") as? SecondViewController
self.navigationController?.pushViewController(secondVC!, animated: true)
}
I hope my descriptive answer will help you. Feel free to ask any query in comments.
Thanks.
Related Topics
How to Reduce the Opacity of the Shadows in Realitykit
Http Request Swift Providing Parameters
Can Not Cast Value of Type Nstaggedpointerstring to Nsdictionary
Making a Http Post Request in Swift 2
Code Highlighting in Latex for Swift
How to Calculate the Energy Per Bin in a Dft
How to Use Tabs to Evenly Space Out Description Strings in Swift
How to Segue Values When My Viewcontroller Is Embedded in an Uinavigationcontroller
Deep Copy of Cmimagebuffer or Cvimagebuffer
Why Does Somestruct() Is Anyobject Return True
Concatenate Literal with Optional String
How to Handle Parameter Validation Swift
Swiftui - Make Toolbar's Navigationlink Use Detail View
Swift For-In Loop with Enumerate on Custom Array2D Class
How to Move Platform with Velocity
In Swift, Can One Use a String to Access a Struct Property