Suche…


Segmente verwenden (Daten weiterleiten)

Um Daten vom aktuellen View-Controller über Segues an den nächsten neuen View-Controller (nicht einen vorherigen View-Controller) zu übergeben, erstellen Sie zunächst ein Segment mit einem Bezeichner im entsprechenden Storyboard. Überschreiben Sie die prepareForSegue Methode Ihres aktuellen View-Controllers. Überprüfen Sie innerhalb der Methode nach dem Segment, das Sie gerade anhand des Bezeichners erstellt haben. Konvertieren Sie den Ziel-View-Controller und übergeben Sie Daten an ihn, indem Sie die Eigenschaften für den Downcast-View-Controller festlegen.

Festlegen eines Bezeichners für ein Segment:

Attributinspektor für ein Segment

Segmente können programmgesteuert oder mithilfe von Schaltflächenaktionsereignissen ausgeführt werden, die im Storyboard durch Drücken von Strg + Ziehen zum Zielansicht-Controller festgelegt werden. Sie können bei Bedarf ein Segment programmatisch aufrufen, indem Sie die Segment-ID im View-Controller verwenden:

Ziel c

- (void)showDetail {
    [self performSegueWithIdentifier:@"showDetailingSegue" sender:self];        
}

Schnell

func showDetail() {
    self.performSegue(withIdentifier: "showDetailingSegue", sender: self)
}

In der überschriebenen Version der prepareForSegue Methode können Sie die prepareForSegue . Sie können die erforderlichen Eigenschaften festlegen, bevor der Zielansicht-Controller geladen wird.

Ziel c

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"showDetailingSegue"]){
        DetailViewController *controller = (DetailViewController *)segue.destinationViewController;
        controller.isDetailingEnabled = YES;
    }
}

Schnell

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetailingSegue" {
        let controller = segue.destinationViewController as! DetailViewController
        controller.isDetailingEnabled = true
    }    
}

DetailViewController ist der Name des zweiten View-Controllers und isDetailingEnabled ist eine öffentliche Variable in diesem View-Controller.

Um dieses Muster zu erweitern, können Sie eine öffentliche Methode in DetailViewController als Pseudo-Initialisierer behandeln, um die erforderlichen Variablen zu initialisieren. Dies dokumentiert Variablen, die in DetailViewController werden müssen, ohne dass der Quellcode gelesen werden muss. Es ist auch ein praktischer Ort, um Standardwerte festzulegen.

Ziel c

- (void)initVC:(BOOL *)isDetailingEnabled {
    self.isDetailingEnabled = isDetailingEnabled
}

Schnell

func initVC(isDetailingEnabled: Bool) {
    self.isDetailingEnabled = isDetailingEnabled
}

Verwenden des Delegatenmusters (Zurückgeben von Daten)

Um Daten vom aktuellen View-Controller zurück an den vorherigen View-Controller zu übergeben, können Sie das Delegatenmuster verwenden.

Geben Sie hier die Bildbeschreibung ein

In diesem Beispiel wird davon showSecondViewController dass Sie im Interface Builder ein showSecondViewController und dass Sie die showSecondViewController auf showSecondViewController . Die Ausgänge und Aktionen müssen auch mit den Namen im folgenden Code verbunden sein.

Erste Ansicht Controller

Der Code für den First View Controller lautet

Schnell

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showSecondViewController", let secondViewController = segue.destinationViewController as? SecondViewController  {
            secondViewController.delegate = self
        }
    }

    // required method of our custom DataEnteredDelegate protocol
    func userDidEnterInformation(info: String) {
        label.text = info
        navigationController?.popViewControllerAnimated(true)
    }
}

Ziel c

@interface FirstViewController : UIViewController <DataEnteredDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@end

@implementation FirstViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    SecondViewController *secondViewController = segue.destinationViewController;
    secondViewController.delegate = self;

}
-(void)userDidEnterInformation:(NSString *)info {
    _label.text = info
    [self.navigationController popViewControllerAnimated:YES];
}
@end

Beachten Sie die Verwendung unseres benutzerdefinierten DataEnteredDelegate Protokolls.

Second View Controller und Protokoll

Der Code für den zweiten View-Controller lautet

Schnell

// 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?
    
    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {
        
        // call this method on whichever class implements our delegate protocol (the first view controller)
        delegate?.userDidEnterInformation(textField.text ?? "")
    }
}

Ziel c

@protocol DataEnteredDelegate <NSObject>
-(void)userDidEnterInformation:(NSString *)info;
@end

@interface SecondViewController : UIViewController 
@property (nonatomic) id <DataEnteredDelegate> delegate;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end

@implementation SecondViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}

- (IBAction) sendTextBackButton:(id)sender{
    [_delegate userDidEnterInformation:textField.text];
}
@end

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

Daten rückwärts mit "Abwickeln" umleiten

Im Gegensatz zu segue können Sie Daten vom aktuellen View-Controller an den Ziel-View-Controller "weiterleiten":

(VC1) -> (VC2)

Mit "Abwickeln" können Sie das Gegenteil tun, Daten vom Ziel- oder aktuellen Ansichts-Controller an den präsentierenden Ansichts-Controller übergeben:

(VC1) <- (VC2)

ANMERKUNG : Achten Sie darauf, dass Sie mit der Funktion "Abwickeln" die Daten zuerst weitergeben können. Danach wird der aktuelle View Controller (VC2) freigegeben.

So geht's:

Zuerst müssen Sie die folgende Deklaration bei dem Presenting View Controller (VC1) hinzufügen. Dies ist der View Controller, an den die Daten übergeben werden sollen:

@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)

Das Wichtigste ist , das Präfix zu verwenden , unwind , um diesen „informiert“ Xcode , dass dies eine Abroll - Methode Ihnen die Möglichkeit, es auch in Storyboard zu verwenden.

Danach müssen Sie die Methode implementieren, sie sieht fast wie ein tatsächliches Segment aus:

@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)
{
    if segue.identifier == "YourCustomIdentifer"
    {
        if let VC2 = segue.sourceViewController as? VC2
        {
            //    Your custom code in here to access VC2 class member
        }

Jetzt haben Sie zwei Möglichkeiten, die Abwicklungsaufrufe aufzurufen:

  1. Sie können "hard code" aufrufen: self.performSegueWithIdentifier("YourCustomIdentifier", sender: self) der die Abwicklung für Sie performSegueWithIdentifier wenn performSegueWithIdentifier .
  2. Sie können die Abwickelmethode mithilfe des storyboard mit dem Objekt "Beenden" verknüpfen: Halten Sie die Taste gedrückt, und ziehen Sie die Schaltfläche, die Sie die Abwickelmethode aufrufen möchten, auf das Objekt "Beenden".

Geben Sie hier die Bildbeschreibung ein

Wenn Sie loslassen, können Sie Ihre benutzerdefinierte Abwickelmethode wählen:

Geben Sie hier die Bildbeschreibung ein

Weitergabe von Daten mithilfe von Closures (Zurückgeben von Daten)

Anstatt das Delegatenmuster zu verwenden , das die Implementierung in verschiedene Teile der UIViewController Klasse UIViewController , können Sie sogar closures , um Daten vor und zurück zu übergeben. Wenn Sie davon ausgehen, dass Sie UIStoryboardSegue , können Sie in der prepareForSegue Methode den neuen Controller einfach in einem Schritt prepareForSegue

final class DestinationViewController: UIViewController {
    var onCompletion: ((success: Bool) -> ())?

    @IBAction func someButtonTapped(sender: AnyObject?) {
        onCompletion?(success: true)
    }
}

final class MyViewController: UIViewController {
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
        guard let destinationController = segue.destinationViewController as? DestinationViewController else { return }
    
        destinationController.onCompletion = { success in
            // this will be executed when `someButtonTapped(_:)` will be called
            print(success)
        }
    }
}

Dies ist ein Beispiel für die Verwendung und es ist besser für Swift zu verwenden. Die Syntax des Objective-C-Blocks ist nicht so einfach, um den Code lesbarer zu machen

Callback-Schließung (Block) verwenden, um Daten zurückzuleiten

Dieses Thema ist ein klassisches Thema in der iOS-Entwicklung, und seine Lösung unterscheidet sich von anderen bereits gezeigten Beispielen. In diesem Beispiel werde ich zeige eine weitere tägliche gemeinsame Nutzung ein: Übergabe von Daten unter Verwendung von closure durch Anpassung delegate pattern auf dieser Seite in Callback - Beispiel closure !

eine Sache , diese Methode überlegen ist delegate pattern ist anstelle von Split die Einrichtung Code in zwei anderen Ort (auf dieser Seite an Delegaten Beispiel aussehen, prepareForSegue , userDidEnterInformation ) eher sie zusammen zu sammeln (nur in prepareForSegue , ich werde es zeigen)

Starten Sie vom Second View Controller aus

Wir müssen herausfinden, wie Callback verwendet wird. Dann können wir es schreiben. Deshalb starten wir vom Second-View-Controller, da wir Callback verwenden. Wenn wir die neue Texteingabe erhalten haben, rufen wir unseren Callback auf und verwenden den Callback-Parameter als Medium Um Daten an den ersten ViewController zurückzuschicken, muss ich feststellen, dass ich mit dem Callback-Parameter gesagt habe. Dies ist sehr wichtig. Neulinge (wie ich es waren) übersehen dies immer und wissen nicht, wo sie den Callback-Abschluss richtig schreiben sollen

In diesem Fall wissen wir also, dass unser Rückruf nur einen Parameter enthält: Text und dessen Typ ist String . Lassen Sie uns ihn deklarieren und als Eigenschaft definieren, da wir den ersten View-Controller mit Daten füllen müssen

Ich kommentiere einfach alle delegate und halte es für Vergleiche

class SecondViewController: UIViewController {

    //weak var delegate: DataEnteredDelegate? = nil
    var callback: ((String?)->())?
    
    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {
        
        //delegate?.userDidEnterInformation(textField.text!)
        callback?(input.text)
        
        self.navigationController?.popViewControllerAnimated(true)
    }
}

Beenden Sie den Controller für die erste Ansicht

Sie müssen nur noch den Callback-Abschluss übergeben, und wir sind fertig, der Abschluss wird die zukünftige Arbeit für uns erledigen, da wir ihn bereits im Second-View-Controller eingerichtet haben

Sehen Sie, wie unser Code im Vergleich zum delegate pattern kürzer delegate pattern

//no more DataEnteredDelegate
class FirstViewController: UIViewController {

    @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
            secondViewController.callback = { text in self.label.text = text }
        }
    }

    // required method of our custom DataEnteredDelegate protocol
    //func userDidEnterInformation(info: String) {
    //    label.text = info
    //}
}

und in letzter Konsequenz wird vielleicht jemand von Ihnen verwirrt, wenn wir nur die Daten (Schließung in diesem Fall) nur auf eine Weise weitergeben, vom ersten Ansichts-Controller zum zweiten, kein direktes Zurückkommen vom zweiten Ansichts-Controller, wie können wir das tun betrachten es als Kommunikationsmittel? Vielleicht sollten Sie es wirklich ausführen und es selbst beweisen. Alles, was ich sagen werde, ist es Parameter , es ist der Parameter des Callback-Abschlusses , der Daten zurückgibt!

Durch Zuweisen von Eigenschaften (Weiterleiten von Daten)

Sie können Daten direkt übergeben, indem Sie die Eigenschaft des nächsten View-Controllers zuweisen, bevor Sie sie drücken oder präsentieren.

class FirstViewController: UIViewController {

    func openSecondViewController() {

        // Here we initialize SecondViewController and set the id property to 492
        let secondViewController = SecondViewController()
        secondViewController.id = 492

        // Once it was assign we now push or present the view controller
        present(secondViewController, animated: true, completion: nil)
    }

}

class SecondViewController: UIViewController {
    
    var id: Int?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Here we unwrapped the id and will get the data from the previous view controller.
        if let id = id {
            print("Id was set: \(id)")
        }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow