it-swarm.com.de

Daten an vorherigen Viewcontroller zurückgeben

Ich versuche, Daten ZURÜCK an den vorherigen viewController zu übergeben. 

Weiß jemand, wie man Daten von ViewController B an ViewController A zurückgibt? Ich möchte also, dass eine Zeichenfolge "von" BIDAddTypeOfDealViewController zu BIDDCCreateViewController wechselt. Ein Benutzer bearbeitet viewController B und ich möchte, dass die bearbeiteten Daten wieder in ViewController A gespeichert werden, wo ich sie dann verwende. 

Ich verwende den Abschnitt "Weitergabe von Daten" von dieser Antwort . Wie sich mein Unterschied unterscheidet: Punkt 3 und 6 erwähnen nur, wann Ansichten geknackt wurden, also habe ich diesen Code in viewWillDisappear eingefügt. Ich denke, das ist richtig? Auch bei Punkt 6 habe ich nicht mit der Feder initialisiert, da diese alt ist. Ich verwende Storyboards. Und diese letzte Zeile habe ich nicht hinzugefügt, da ich nicht glaube, dass ich sie drängen müsste. Ein Knopfdruck auf meinem Storyboard bringt mich schon weiter. 

Ich denke, das Problem kann in BIDDCCreateViewController auftreten. Ich habe die Methode, kann sie jedoch nicht ausführen. Um eine Methode auszuführen, sollte es [self-Methode] gehen. Das kann ich nicht. Nun, das rate ich gerade. 

Es kompiliert und läuft gut, es wird nichts protokolliert, daher weiß ich nicht, ob es funktioniert. 

UPDATE: Ich kann die 'sendDataToA'-Methode nicht ausführen. 

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

 @interface BIDDCCreateViewController : UIViewController
 @property (strong, nonatomic) NSString *placeId;
- (IBAction)gotoBViewController:(id)sender;
@end


#import "BIDDCCreateViewController.h"
#import "BIDAddTypeOfDealViewController.h"

@implementation BIDDCCreateViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSLog(@"SUCCESSFULLY PASSED PLACE ID: %@", self.placeId);
}

-(void)sendDataToA:(NSString *)myStringData
{

    NSLog(@"Inside sendDataToA");
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Your string Data Showing" message:myStringData delegate:self cancelButtonTitle:@"Ok " otherButtonTitles:nil];
    [alert show];
}

- (IBAction)gotoBViewController:(id)sender {
    NSLog(@"pressed");
    BIDAddTypeOfDealViewController *bidAddType = [[BIDAddTypeOfDealViewController alloc]init];
    bidAddType.delegate = self;

}
@end


@protocol senddataProtocol <NSObject>
-(void)sendDataToA:(NSString *)myStringData;
@end

#import <UIKit/UIKit.h>
@interface BIDAddTypeOfDealViewController : UIViewController <UITextFieldDelegate>//Using this delegate for data a user inputs
@property(nonatomic,assign)id delegate;
//other textfield outlets not relevant
- (IBAction)chooseDiscountDeal:(id)sender;
@end

#import "BIDAddTypeOfDealViewController.h"

@interface BIDAddTypeOfDealViewController ()

@end

@implementation BIDAddTypeOfDealViewController
@synthesize delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void)viewWillDisappear:(BOOL)animated
{
    [delegate sendDataToA:@"Apple"];
}
@end
48
Anthony

Sie können einen Delegierten verwenden. In Ihrem ViewController B müssen Sie also ein Protokoll erstellen, das Daten an Ihren ViewController A zurücksendet. Ihr ViewController A würde ein Delegierter von ViewController B werden. 

Wenn Sie mit Objective C noch nicht vertraut sind, schauen Sie bitte nach Was ist Delegierter .

Protokoll in ViewControllerB.h erstellen:

#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 Ihrem ViewControllerA: Wenn Sie zu ViewControllerB wechseln 

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

und definiere deine Funktion: 

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

Bearbeitet:

Sie können dieses Beispiel sehen: So können Sie Daten an den vorherigen Viewcontroller zurückgeben: Tutorial-Link

88
Erhan Demirci

Eine kürzere und einfachere Methode als Protokoll/Delegat besteht darin, eine Schließung zu erstellen:

Um in meinem Fall einen String zurückzuschicken ... In ViewControllerA:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let viewControllerB = segue.destination as? ViewControllerB {
        viewControllerB.callback = { message in
            //Do what you want in here!
        }
    }
}

In ViewControllerB:

var callback : ((String) -> Void)?

@IBAction func done(sender: AnyObject) {
    callback?("Hi")
    self.dismiss(animated: true, completion: nil)
}
51
Heinrisch

Schnell: Zurücksenden von Daten unter Verwendung des Delegatenmusters

Meine vollständige Antwort, die das Übergeben von Daten in beide Richtungen abdeckt, lautet hier . Meine Antwort zur Erläuterung des Delegiertenmusters lautet hier .

Um Daten vom zweiten Ansichtscontroller an den ersten Ansichtscontroller zurückzuleiten, verwenden Sie ein Protokoll und einen Delegaten. Dieses Video ist ein sehr anschaulicher Überblick über diesen Prozess:

Das folgende Beispiel basiert auf dem Video (mit einigen Änderungen).

enter image description here

Erstellen Sie das Storyboard-Layout im Interface Builder. Nochmals, um den Übergang zu schaffen, einfach Control Ziehen Sie von der Schaltfläche zum Second View Controller. Setzen Sie die Segue-ID auf showSecondViewController. Vergessen Sie auch nicht, die Ausgänge und Aktionen mit den Namen im folgenden Code zu verbinden.

First View Controller

Der Code für den First View Controller lautet

import UIKit

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showSecondViewController" {
            let secondViewController = segue.destinationViewController as! SecondViewController
            secondViewController.delegate = self
        }
    }

    func userDidEnterInformation(info: String) {
        label.text = info
    }
}

Beachten Sie die Verwendung unseres benutzerdefinierten Protokolls DataEnteredDelegate.

Second View Controller und Protokoll

Der Code für den zweiten Ansichtscontroller lautet

import UIKit

// protocol used for sending data back
protocol DataEnteredDelegate: class {
    func userDidEnterInformation(info: String)
}

class SecondViewController: UIViewController {

    // making this a weak variable so that it won't create a strong reference cycle
    weak var delegate: DataEnteredDelegate? = nil

    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: UIButton) {

        // call this method on whichever class implements our delegate protocol
        delegate?.userDidEnterInformation(textField.text!)

        // go back to the previous view controller
        self.navigationController?.popViewControllerAnimated(true)
    }
}

Beachten Sie, dass sich protocol außerhalb der View Controller-Klasse befindet.

Das ist es. Wenn Sie die App jetzt ausführen, sollten Sie in der Lage sein, Daten vom zweiten View-Controller an den ersten zurückzusenden.

40
Suragch

Bearbeiten: Verwenden Sie @ Erhans Lösung oben. Nicht dieser. Dies ist keine gute Lösung.

Das wird helfen. Schreiben Sie dies in Ihren ViewControllerB. 

    // Get array of current navigation stack
    NSArray *arrayViewControllers = [self.navigationController viewControllers];

    // Get previous viewController object from it
    YOUR_VIEW_CONTROLLER_NAME *objViewController = (YOUR_VIEW_CONTROLLER_NAME *)[arrayViewControllers objectAtIndex:arrayViewControllers.count-2];

    // For safety this check is needed. whether it the class that you want or not.
    if ([objViewController isKindOfClass:[YOUR_VIEW_CONTROLLER_NAME class]])
    {
        // Access properties of YOUR_VIEW_CONTROLLER_NAME here
        objViewController.yourProperty = YOUR_VALUE;
    }
2
Akshit Zaveri

Wie Erhan Demirci antwortete, können Sie Delegierte verwenden. Delegaten sind hilfreich, wenn Sie Daten an einen einzelnen View-Controller übergeben möchten.

NSNotificationCenter ist eine weitere bequeme Möglichkeit, Daten zwischen Viewcontrollern/Objekten zu übertragen. Dies ist sehr hilfreich bei der Übertragung von Daten innerhalb der Anwendung.

dokumentation lesen hier .

1
Abdullah Umer

Benutzerdefinierter Delegat ist die beste Option zum Verschieben von Daten. Sie können dies jedoch auch versuchen.

Sie können NSUserDefaults verwenden, um die Daten an einen beliebigen Ort zu verschieben.

Swift 3 Code

UserDefaults.standard.set(<Value>, forKey: <Key>) 
// To set data

UserDefaults.standard.object(forKey: <Key>) 
// To get data

Sie können NSNotification auch zum Verschieben von Daten verwenden.

NotificationCenter.default.post(name: Notification.Name(rawValue: "refresh"), object: myDict) 

NotificationCenter.default.addObserver(self, selector: #selector(refreshList(_:)), name: NSNotification.Name(rawValue: "refresh"), object: nil)
1
Saurabh Sharma

Es gibt ein Protokoll, das geschlossen wird. Mit dem Schließen müssen wir Gedächtnislecks vermeiden, indem wir ein schwaches Selbst (oder ein nicht besessenes Selbst) verwenden. Mit dem Protokoll würde es einen pro viewController geben, den Sie "überwachen" möchten, und am Ende Dutzende Delegierte implementieren. Hier habe ich noch eine andere einfache Lösung in Swift:

Erstellen Sie in einer neuen oder vorhandenen Datei (zum Beispiel: UIViewController+Extensions.Swift) dieses Protokoll:

protocol ViewControllerBackDelegate: class {
    func back(from viewController: UIViewController)
}

In LEVEL-2 viewController, wo ein Rückruf erfolgen soll, wenn Zurück gedrückt wird von:

class LevelTwoViewController: UIViewController {
    // making this a weak variable so that it won't create a strong reference cycle
    weak var delegate: ViewControllerBackDelegate? = nil

    override func willMove(toParentViewController parent: UIViewController?) {
        super.willMove(toParentViewController: parent)
        if (parent == nil) {
            delegate?.back(from: self)
        }
    }
}

Da delegate optional ist, können Sie diesen Code einer Basisklasse Ihrer View-Controller hinzufügen. Ich würde hinzufügen, wo es sein muss.

Nehmen Sie in Ihrem LEVEL-1 viewController an, dass Sie LEVEL-2 über ein Segment im Storyboard aufrufen:

class LevelOneViewController: UIViewController {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "Go to Level 2") {
            if let vc = segue.destination as? LevelTwoViewController {
                vc.selectedItems = self.selectedItems // passing data-in
                vc.delegate = self
            }
        }
        // repeat `if` for another sub-level view controller
    }
}

extension LevelOneViewController: ViewControllerBackDelegate {    
    func back(from viewController: UIViewController) {
        if let vc = viewController as? LevelTwoViewController {
            self.selectedItems = vc.selectedItems
            // call update if necessary
        }
        // repeat `if` for another sub-level view controller
    }
}
  • es ist nur ein Protokoll erforderlich.
  • nur eine Erweiterung pro ViewController der ersten Ebene.
  • keine Änderungen an der untergeordneten Ansicht von viewController, wenn mehr/weniger Daten zurückgegeben werden müssen
  • datenausgabe wie Dateneingabe in prepare(for:sender:)
0
John Pang