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
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
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)
}
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).
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.
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;
}
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 .
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)
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
}
}
prepare(for:sender:)