iOS
Daten zwischen View-Controllern übergeben
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:
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.
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:
- Sie können "hard code" aufrufen:
self.performSegueWithIdentifier("YourCustomIdentifier", sender: self)
der die Abwicklung für SieperformSegueWithIdentifier
wennperformSegueWithIdentifier
. - 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".
Wenn Sie loslassen, können Sie Ihre benutzerdefinierte Abwickelmethode wählen:
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)")
}
}
}