Swift Delegate Beetween Two Vc Without Segue

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:

  1. Define a delegate protocol for object B.
  2. Give object B an optional delegate variable. This variable should be weak.
  3. 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.
  4. 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.
  5. 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

  1. 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.


  1. This delegate is not needed

, if you simply want to go to Next Screen which is SecondViewController in your case.


  1. 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



Leave a reply



Submit