How to Send Data Back by Popviewcontrolleranimated for Swift

How to send data back by popViewControllerAnimated for Swift?

You can pass data back using delegate

  1. Create protocol in ChildViewController
  2. Create delegate variable in ChildViewController
  3. Extend ChildViewController protocol in MainViewController
  4. Give reference to ChildViewController of MainViewController when navigate
  5. Define delegate Method in MainViewController
  6. Then you can call delegate method from ChildViewController

Example

In ChildViewController: Write code below...

protocol ChildViewControllerDelegate
{
func childViewControllerResponse(parameter)
}

class ChildViewController:UIViewController
{
var delegate: ChildViewControllerDelegate?
....
}

In MainViewController

// extend `delegate`
class MainViewController:UIViewController,ChildViewControllerDelegate
{
// Define Delegate Method
func childViewControllerResponse(parameter)
{
.... // self.parameter = parameter
}
}

There are two options:

A) with Segue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let goNext = segue.destinationViewController as ChildViewController
goNext.delegate = self
}

B) without Segue

let goNext = storyboard?.instantiateViewControllerWithIdentifier("childView") as ChildViewController
goNext.delegate = self
self.navigationController?.pushViewController(goNext, animated: true)

Method Call

self.delegate?.childViewControllerResponse(parameter)

Swift popViewController Send Data

You seem to be trying to pass data from SelectTag to MyPage.

One way to do this is to use the delegate pattern.

Create a SelectTagDelegate:

protocol SelectTagDelegate : class {
func didSelectTag(tags: [Int])
}

Add this property in SelectTag:

weak var delegate: SelectTagDelegate?

And then change endSelectTag to:

@IBAction func endSelectTag(_ sender: Any) {
delegate?.didSelectTag(tags: selectedTag)
self.navigationController?.popViewController(animated: true)
}

Make MyPage conform to SelectTagDelegate by implementing didSelectTag:

extension MyPage: SelectTagDelegate {
func didSelectTag(tags: [Int]) {
seleteTag = tags
}
}

Now, when you are presenting SelectTag, set self as the delegate.

let selectTag = // get VC from storyboard or use segue.destination depending on your situation
selectTag.delegate = self
// present the VC

Swift – Using popViewController and passing data to the ViewController you're returning to

So I figured it out, based mostly from this post – http://makeapppie.com/2014/09/15/swift-swift-programmatic-navigation-view-controllers-in-swift/

In SecondViewController, above the class declaration, add this code:

protocol SecondVCDelegate {
func didFinishSecondVC(controller: SecondViewController)
}

Then inside of SecondViewContoller add a class variable:

var delegate: MeditationVCDelegate! = nil

Then inside of your function that your button targets, add this:

self.navigationController?.popViewControllerAnimated(true)
delegate.didFinishSecondVC(self)

What we're doing here is doing the pop in SecondViewController, and not passing any data, but since we've defined a protocol, we're going to use that in ViewController to handle the data.

So next, in ViewController, add the protocol you defined in SecondViewController to the list of classes ViewController inherits from:

class ViewController: UIViewController, SecondVCDelegate { ... your code... }

You'll need to add the function we defined in the new protocol in order to make the compiler happy. Inside of ViewController's class, add this:

func didFinishSecondVC(controller: SecondViewController) {
self.myBoolVar = true
controller.navigationController?.popViewControllerAnimated(true)
}

In SecondViewController where we're calling didFinishSecondVC, we're calling this method inside of the ViewController class, the controller we're popping to. It's similar to if we wrote this code inside of SecondViewController but we've written it inside of ViewController and we're using a delegate to manage the messaging between the two.

Finally, in ViewController, in the function we're targeting to push to SecondViewController, add this code:

let secondVC = secondViewController()
secondVC.delegate = self
self.navigationController?.pushViewController(secondVC, animated: true)

That's it! You should be all set to pass code between two view controllers without using storyboards!

how to pass data after pop view controller in swift

In the ScanView you are creating the new instance of UploadMain, that is not available in window hierarchy, So that data is not available to the UploadMain. To solve your problem you need to create one protocol and pass the delegate of that protocol to ScanView. So create one protocol like this.

protocol IsbnDelegate {
func passData(isbnStr: String)
}

Now inherit this protocol in UploadMain and override its method passData in the UploadMain like below

class UploadMain: UIViewController,UITextFieldDelegate,IsbnDelegate  {

//your code

//Add this method
func passData(isbnStr: String) {
self.ISBN.text = isbnStr
}

//Also override prepareForSegue like this

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destVC = segue.destinationViewController as! ScanView
destVC.delegate = self
}
}

After that create one delegate object in ScanView, Change your code of ScanView like this

import UIKit
import AVFoundation
import Foundation


class ScanView : UIViewController, AVCaptureMetadataOutputObjectsDelegate {



let session : AVCaptureSession = AVCaptureSession()
var previewLayer : AVCaptureVideoPreviewLayer!
var detectionString : String!
let apiKey : String = "---------dddddd"
var delegate: IsbnDelegate?

override func viewDidLoad() {
super.viewDidLoad()

// For the sake of discussion this is the camera
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

// Create a nilable NSError to hand off to the next method.
// Make sure to use the "var" keyword and not "let"
var error : NSError? = nil
var input: AVCaptureDeviceInput = AVCaptureDeviceInput()
do {
input = try AVCaptureDeviceInput(device: device) as AVCaptureDeviceInput
} catch let myJSONError {
print(myJSONError)
}

// If our input is not nil then add it to the session, otherwise we're kind of done!
if input != AVCaptureDeviceInput() {
session.addInput(input)
}
else {
// This is fine for a demo, do something real with this in your app. :)
print(error)
}

let output = AVCaptureMetadataOutput()
output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
session.addOutput(output)
output.metadataObjectTypes = output.availableMetadataObjectTypes


previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.frame = self.view.bounds
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
self.view.layer.addSublayer(previewLayer)

// Start the scanner. You'll have to end it yourself later.
session.startRunning()

}



// This is called when we find a known barcode type with the camera.
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

var highlightViewRect = CGRectZero
var barCodeObject : AVMetadataObject!
let barCodeTypes = [AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code]


// The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
for metadata in metadataObjects {

for barcodeType in barCodeTypes {

if metadata.type == barcodeType {
barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)

highlightViewRect = barCodeObject.bounds

detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue

self.session.stopRunning()

self.alert(detectionString)

// Daum Book API 호출
let apiURI = NSURL(string: "https://apis.daum.net/search/book?apikey=\(apiKey)&q=\(detectionString)&searchType=isbn&output=json")

let apidata : NSData? = NSData(contentsOfURL: apiURI!)

NSLog("API Result = %@", NSString(data: apidata!, encoding: NSUTF8StringEncoding)!)


//Here We are passing the data of your ScanView to UploadMain
self.delegate.passData(self.detectionString!)

break
}

}
}

print(detectionString)
self.navigationController?.popViewControllerAnimated(true)

}



func alert(Code: String){
let actionSheet:UIAlertController = UIAlertController(title: "Barcode", message: "\(Code)", preferredStyle: UIAlertControllerStyle.Alert)

// for alert add .Alert instead of .Action Sheet
// start copy
let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler:
{
(alertAction:UIAlertAction!) in

// action when pressed
self.session.startRunning()
})


actionSheet.addAction(firstAlertAction)

}

}

For more detail about protcol follow this link

1) Apple Documentation

2) Tutorial 1

3) Tutorial 2

Hope this will help you.

it possible to Pass Data with popViewControllerAnimated?

The best way to do it is by using a delegate.

//SecVCDelegate.h

#import <Foundation/Foundation.h>

@protocol SecVSDelegate <NSObject>

@optional
- (void)secVCDidDismisWithData:(NSObject*)data;
@end

//SecVC.h

#import <UIKit/UIKit.h>
#import "SecVSDelegate.h"

@interface SecVC : UIViewController

/** Returns the delegate */
@property (nonatomic, assign) id<SecVSDelegate> delegate;

@end

//SecVC.M

...

- (void) dealloc
{
...
delegate = nil
...
}

When ever you popViewControllerAnimated, right after it (or before it) you do this

if(_delegate && [_delegate respondsToSelector:@selector(secVCDidDismisWithData:)])
{
[_delegate secVCDidDismisWithData:myDataObject];
}

And in the MainVC you must be certain that you implement the delegate function
//MainVC.m

- (void)secVCDidDismisWithData
{
//do whatever you want with the data
}

To avoid any warnings you must tell that the MainVC class implements the delegate like this:

//MainVC.h

#import "SecVCDelegate.h"
...
@interface MainVC : UIViewController <SecVCDelegate>
...
secVCInstance.delegate = self;
[self.navigationController pushViewController:secVCInstance];
...

Pass data back to previous viewcontroller

You can use a delegate. So in your ViewController B you need to create a protocol that sends data back to your ViewController A. Your ViewController A would become a delegate of ViewController B.

If you are new to objective C, please look at What is Delegate.

Create protocol in ViewControllerB.h :

#import <UIKit/UIKit.h>

@protocol senddataProtocol <NSObject>

-(void)sendDataToA:(NSArray *)array; //I am thinking my data is NSArray, you can use another object for store your information.

@end

@interface ViewControllerB : UIViewController

@property(nonatomic,assign)id delegate;

ViewControllerB.m

@synthesize delegate;
-(void)viewWillDisappear:(BOOL)animated
{
[delegate sendDataToA:yourdata];

}

in your ViewControllerA : when you go to ViewControllerB

ViewControllerA *acontollerobject=[[ViewControllerA alloc] initWithNibName:@"ViewControllerA" bundle:nil];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];

and define your function:

-(void)sendDataToA:(NSArray *)array
{
// data will come here inside of ViewControllerA
}

Edited :

You can See this example : How you can Pass data back to previous viewcontroller: Tutorial link

Pass data back to uiviewcontroller on pop (NavigationController.PopViewController)

NavigationController keeps track of all the ViewControllers as an array: NavigationController.ViewControllers

You can get an existing instance of the ViewController Type from this array via following code:
(You may write this method in BaseViewController if you have it.)

public T InstanceFromNavigationStack<T> () where T : UIViewController
{
return (T)NavigationController.ViewControllers.FirstOrDefault(v => v is T);
}

Then use it like :

var myVCInstance = InstanceFromNavigationStack<MyTargetViewController>();
if(myVCInstance != null)
{
//Assign a value like
myVCInstance.MyVariable = "MyValue";

//Or call a method like
myVCInstance.MethodToReloadView("MyValue")
}
//Go Back Navigation Code
//Then here write your navigation logic to go back.

This not only helps passing data in Previous ViewController, but Any ViewController in the stack. Simply pass the Type of it to get an Instance from Stack.

NOTE: This should work if your Navigation stack doesn't have multiple instance of the same ViewController Type.

Swift / how to call delegate with popViewController

You can set the delegate of My3rdVC in the prepareForSegue method of My2ndVC.

class My2ndVC: UIViewController, PassClubDelegate {

...

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

super.prepareForSegue(segue, sender: sender)

switch segue.destinationController {
case let controller as My3rdVC:
controller.passClubDelegate = self
}
}
}

This is assuming you have created a segue in your storyboard that pushes My3rdVC from My2ndVC onto the navigation controller stack, which I'm assuming you have. So just try simply pasting this prepareForSegue method into My2ndVC and see if it works.

UPDATE

let vc = stb.instantiateViewControllerWithIdentifier("My3rdVC") as! My3rdVC

vc.passClubDelegate = self

navigationController?.pushViewController(vc, animated: true)

Programmatically go back to previous ViewController in Swift

Swift 3:

If you want to go back to the previous view controller

_ = navigationController?.popViewController(animated: true)

If you want to go back to the root view controller

_ = navigationController?.popToRootViewController(animated: true)

If you are not using a navigation controller then pls use the below code.

self.dismiss(animated: true, completion: nil)

animation value you can set according to your requirement.



Related Topics



Leave a reply



Submit