Ich bin neu bei iOS und Objective-C und dem gesamten MVC-Paradigma. Ich bleibe dabei bei Folgendem:
Ich habe eine Ansicht, die als Dateneingabeformular fungiert, und ich möchte dem Benutzer die Möglichkeit geben, mehrere Produkte auszuwählen. Die Produkte werden in einer anderen Ansicht mit einer UITableViewController
aufgelistet und ich habe mehrere Auswahlmöglichkeiten aktiviert.
Meine Frage ist, wie übertrage ich die Daten von einer Ansicht zu einer anderen? Ich werde die Auswahlmöglichkeiten für die Variable UITableView
in einem Array enthalten, aber wie gebe ich diese dann an die vorherige Formularansicht zurück, damit sie zusammen mit den anderen Daten beim Senden des Formulars zusammen mit Core Data gespeichert werden kann?
Ich habe herumgesurft und gesehen, wie einige Leute im App-Delegierten ein Array deklarieren. Ich habe etwas über Singletons gelesen, verstehe aber nicht, was es ist und ich habe etwas über das Erstellen eines Datenmodells gelesen.
Was wäre der richtige Weg, dies zu tun und wie würde ich das anstellen?
Diese Frage scheint bei stackoverflow sehr beliebt zu sein. Ich dachte, ich würde versuchen, eine bessere Antwort zu geben, um Leuten zu helfen, die in der Welt von iOS wie mir anfangen.
Ich hoffe, dass diese Antwort für die Leute klar genug ist und dass ich nichts übersehen habe.
Weiterleiten von Daten
Weiterleiten von Daten an einen View Controller von einem anderen View Controller aus. Sie würden diese Methode verwenden, wenn Sie ein Objekt/einen Wert von einem View-Controller an einen anderen View-Controller übergeben möchten, den Sie möglicherweise in einen Navigations-Stack verschieben.
Für dieses Beispiel haben wir ViewControllerA
und ViewControllerB
Um einen BOOL
-Wert von ViewControllerA
an ViewControllerB
zu übergeben, würden wir Folgendes tun.
in ViewControllerB.h
eine Eigenschaft für die BOOL
erstellen
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
musst du etwas über ViewControllerB
sagen, also benutze ein
#import "ViewControllerB.h"
Dort, wo Sie die Ansicht laden möchten, z. didSelectRowAtIndex
oder einige IBAction
müssen Sie die Eigenschaft in ViewControllerB
setzen, bevor Sie sie in den Nav-Stack verschieben.
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.isSomethingEnabled = YES;
[self pushViewController:viewControllerB animated:YES];
Dies setzt isSomethingEnabled
in ViewControllerB
auf BOOL
Wert YES
.
Weiterleiten von Daten über Segmente
Wenn Sie Storyboards verwenden, verwenden Sie höchstwahrscheinlich Segmente und benötigen dieses Verfahren, um Daten weiterzuleiten. Dies ist ähnlich wie oben, aber anstatt die Daten vor dem Push des View-Controllers zu übergeben, verwenden Sie eine aufgerufene Methode
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
Um eine BOOL
von ViewControllerA
an ViewControllerB
zu übergeben, würden wir Folgendes tun:
in ViewControllerB.h
eine Eigenschaft für die BOOL
erstellen
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
musst du etwas über ViewControllerB
sagen, also benutze ein
#import "ViewControllerB.h"
Erstellen Sie im Storyboard ein Segment von ViewControllerA
bis ViewControllerB
und geben Sie ihm eine Kennung. In diesem Beispiel nennen wir es "showDetailSegue"
.
Als Nächstes müssen wir die Methode ViewControllerA
hinzufügen, die aufgerufen wird, wenn ein Segment ausgeführt wird. Aus diesem Grund müssen wir ermitteln, welches Segment aufgerufen wurde, und dann etwas tun. In unserem Beispiel werden wir nach "showDetailSegue"
suchen und wenn dies ausgeführt wird, übergeben wir unseren BOOL
-Wert an ViewControllerB
.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
controller.isSomethingEnabled = YES;
}
}
Wenn Sie Ihre Ansichten in einen Navigationscontroller eingebettet haben, müssen Sie die obige Methode leicht ändern
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
controller.isSomethingEnabled = YES;
}
}
Dies setzt isSomethingEnabled
in ViewControllerB
auf BOOL
Wert YES
.
Daten zurückgeben
Um Daten von ViewControllerB
an ViewControllerA
zurückzuschicken, müssen Sie Protokolle und Delegierte oder Blöcke verwenden. Letzteres kann als lose gekoppelter Mechanismus für Rückrufe verwendet werden.
Dazu machen wir ViewControllerA
zu einem Delegierten von ViewControllerB
. Dadurch kann ViewControllerB
eine Nachricht an ViewControllerA
zurücksenden, sodass wir Daten zurücksenden können.
Damit ViewControllerA
ein Delegierter von ViewControllerB
ist, muss es dem Protokoll von ViewControllerB
entsprechen, das wir angeben müssen. Dies sagt ViewControllerA
, welche Methoden es implementieren muss.
In ViewControllerB.h
, unterhalb von #import
, aber oberhalb von @interface
geben Sie das Protokoll an.
@class ViewControllerB;
@protocol ViewControllerBDelegate <NSObject>
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
@end
als nächstes müssen Sie noch in ViewControllerB.h
eine delegate
-Eigenschaft einrichten und in ViewControllerB.m
synthetisieren.
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
In ViewControllerB
rufen wir eine Nachricht über die delegate
auf, wenn der View-Controller geöffnet wird.
NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
Das war's für ViewControllerB
. Geben Sie jetzt in ViewControllerA.h
ViewControllerA
an, ViewControllerB
zu importieren und dessen Protokoll einzuhalten.
#import "ViewControllerB.h"
@interface ViewControllerA : UIViewController <ViewControllerBDelegate>
Implementieren Sie in ViewControllerA.m
die folgende Methode aus unserem Protokoll
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(@"This was returned from ViewControllerB %@",item);
}
Bevor Sie viewControllerB
in den Navigationsstapel verschieben, müssen Sie ViewControllerB
mitteilen, dass ViewControllerA
sein Stellvertreter ist. Andernfalls wird ein Fehler angezeigt.
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate = self
[[self navigationController] pushViewController:viewControllerB animated:YES];
NSNotification Center Es ist eine andere Möglichkeit, Daten zu übergeben.
// add observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil];
-(void) handleDeepLinking:(NSNotification *) notification {
id someObject = notification.object // some custom object that was passed with notification fire.
}
// post notification
id someObject;
[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject];
Zurückgeben von Daten von einer Klasse an eine andere (Eine Klasse kann ein beliebiger Controller, ein Netzwerk-/Sitzungsmanager, eine UIView-Unterklasse oder eine andere Klasse sein.)
Blöcke sind anonyme Funktionen.
In diesem Beispiel werden Daten von Controller B an Controller A übergeben.
einen Block definieren
@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h
add Block Handler (Listener) wo Sie einen Wert benötigen (zum Beispiel benötigen Sie Ihre API-Antwort in ControllerA oder benötigen Sie ContorllerB-Daten auf A)
// in ContollerA.m
- (void)viewDidLoad {
[super viewDidLoad];
__unsafe_unretained typeof(self) weakSelf = self;
self.selectedVoucherBlock = ^(NSString *voucher) {
weakSelf->someLabel.text = voucher;
};
}
Gehe zu Controller B
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
[self.navigationController pushViewController:vc animated:NO];
feuerblock
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
NSString *voucher = vouchersArray[indexPath.row];
if (sourceVC.selectVoucherBlock) {
sourceVC.selectVoucherBlock(voucher);
}
[self.navigationController popToViewController:sourceVC animated:YES];
}
Hier und in StackOverflow gibt es jede Menge Erklärungen, aber wenn Sie als Anfänger nur versuchen, etwas Grundlegendes zum Laufen zu bringen, schauen Sie sich dieses YouTube-Tutorial an (es hat mir geholfen, endlich zu verstehen, wie es geht).
Das folgende Beispiel basiert auf dem Video. Die Idee ist, eine Zeichenfolge aus dem Textfeld im First View Controller an die Beschriftung im Second View Controller zu übergeben.
Erstellen Sie das Storyboard-Layout im Interface Builder. Um den Übergang zu schaffen, müssen Sie nur Control Klicken Sie auf die Schaltfläche und ziehen Sie sie zum Second View Controller.
First View Controller
Der Code für den First View Controller lautet
import UIKit
class FirstViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
// This function is called before the segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// get a reference to the second view controller
let secondViewController = segue.destination as! SecondViewController
// set a variable in the second view controller with the String to pass
secondViewController.receivedString = textField.text!
}
}
Second View Controller
Und der Code für den Second View Controller ist
import UIKit
class SecondViewController: UIViewController {
@IBOutlet weak var label: UILabel!
// This variable will hold the data being passed from the First View Controller
var receivedString = ""
override func viewDidLoad() {
super.viewDidLoad()
// Used the text from the First View Controller to set the label
label.text = receivedString
}
}
Vergiss nicht
UITextField
und UILabel
an.Verwenden Sie ein Protokoll und einen Delegaten , um Daten von dem zweiten Ansichtscontroller an den ersten Ansichtscontroller zurückzugeben. 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 prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destination 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: AnyObject) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(info: textField.text!)
// go back to the previous view controller
_ = self.navigationController?.popViewController(animated: 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.
Das M in MVC ist für "Model" und im MVC-Paradigma besteht die Rolle der Modellklassen darin, die Daten eines Programms zu verwalten. Ein Modell ist das Gegenteil einer Ansicht. Eine Ansicht kann Daten anzeigen, weiß jedoch nicht, was mit Daten zu tun ist, wohingegen ein Modell alles über die Arbeit mit Daten weiß, aber nichts über die Anzeige. Modelle können kompliziert sein, müssen es aber nicht sein - das Modell für Ihre App ist möglicherweise so einfach wie ein Array von Strings oder Wörterbüchern.
Die Rolle eines Controllers besteht darin, zwischen Ansicht und Modell zu vermitteln. Daher benötigen sie einen Verweis auf ein oder mehrere Ansichtsobjekte und ein oder mehrere Modellobjekte. Angenommen, Ihr Modell besteht aus einem Array von Wörterbüchern, wobei jedes Wörterbuch eine Zeile in Ihrer Tabelle darstellt. In der Stammansicht Ihrer App wird diese Tabelle angezeigt. Möglicherweise ist das Array aus einer Datei geladen. Wenn der Benutzer beschließt, der Tabelle eine neue Zeile hinzuzufügen, tippen Sie auf eine Schaltfläche, und Ihr Controller erstellt ein neues (veränderbares) Wörterbuch und fügt es dem Array hinzu. Um die Zeile auszufüllen, erstellt der Controller einen Detailansicht-Controller und gibt ihm das neue Wörterbuch. Der Detailansicht-Controller füllt das Wörterbuch aus und kehrt zurück. Das Wörterbuch ist bereits Teil des Modells, sodass nichts anderes passieren muss.
Es gibt verschiedene Möglichkeiten, wie Daten in einer anderen Klasse in iOS empfangen werden können. Zum Beispiel -
NSUserDefaults
- um später darauf zuzugreifenFür das einfache Szenario der Übergabe eines Werts an eine andere Klasse, deren Zuordnung in der aktuellen Klasse erfolgt, wäre die gebräuchlichste und bevorzugte Methode das direkte Setzen von Werten nach der Zuordnung. Dies geschieht wie folgt:
Wir können es mit zwei Controllern verstehen - Controller1 und Controller2
Angenommen, Sie möchten in der Klasse Controller1 das Controller2-Objekt erstellen und es mit einem übergebenen String-Wert als Push übergeben. Dies kann wie folgt gemacht werden: -
- (void)pushToController2 {
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passValue:@"String"];
[self pushViewController:obj animated:YES];
}
Bei der Implementierung der Klasse Controller2 wird diese Funktion
@interface Controller2 : NSObject
@property (nonatomic , strong) NSString* stringPassed;
@end
@implementation Controller2
@synthesize stringPassed = _stringPassed;
- (void) passValue:(NSString *)value {
_stringPassed = value; //or self.stringPassed = value
}
@end
Sie können die Eigenschaften der Controller2-Klasse auch direkt wie folgt festlegen:
- (void)pushToController2 {
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj setStringPassed:@"String"];
[self pushViewController:obj animated:YES];
}
Um mehrere Werte zu übergeben, können Sie die folgenden Parameter verwenden: -
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passValue:@“String1” andValues:objArray withDate:date];
Wenn Sie mehr als 3 Parameter übergeben müssen, die sich auf ein gemeinsames Feature beziehen, können Sie die Werte in einer Model-Klasse speichern und dieses modelObject an die nächste Klasse übergeben
ModelClass *modelObject = [[ModelClass alloc] init];
modelObject.property1 = _property1;
modelObject.property2 = _property2;
modelObject.property3 = _property3;
Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passmodel: modelObject];
Also in Kürze, wenn Sie wollen -
1) set the private variables of the second class initialise the values by calling a custom function and passing the values.
2) setProperties do it by directlyInitialising it using the setter method.
3) pass more that 3-4 values related to each other in some manner , then create a model class and set values to its object and pass the object using any of the above process.
Hoffe das hilft
Nach weiteren Nachforschungen schien es, dass Protokolle und Delegierte der richtige Weg sind, den Apple bevorzugt.
Am Ende habe ich dieses Beispiel verwendet
Daten zwischen View-Controllern und anderen Objekten freigeben @ iPhone Dev SDK
Funktionierte gut und erlaubte mir, eine Zeichenfolge und ein Array vor und zurück zwischen meinen Ansichten zu übergeben.
Danke für deine Hilfe
Ich finde die einfachste und eleganteste Version mit Durchlaufblöcken. Geben Sie dem View-Controller einen Namen, der auf zurückgegebene Daten als "A" wartet und den View-Controller als "B" zurückgibt. In diesem Beispiel möchten wir zwei Werte erhalten: den ersten von Typ1 und den zweiten von Typ2.
Angenommen, wir verwenden Storyboard, legt der erste Controller einen Callback-Block fest, zum Beispiel während der Vorbereitung des Segments:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[BViewController class]])
{
BViewController *viewController = segue.destinationViewController;
viewController.callback = ^(Type1 *value1, Type2 *value2) {
// optionally, close B
//[self.navigationController popViewControllerAnimated:YES];
// let's do some action after with returned values
action1(value1);
action2(value2);
};
}
}
und "B" View Controller sollten die Callback-Eigenschaft BViewController.h deklarieren:
// it is important to use "copy"
@property (copy) void(^callback)(Type1 *value1, Type2 *value2);
Als in der Implementierungsdatei BViewController.m, nachdem wir gewünschte Werte für die Rückgabe unseres Callbacks haben, sollte aufgerufen werden
if (self.callback)
self.callback(value1, value2);
Dabei ist zu beachten, dass bei der Verwendung von Block häufig starke und __schwache Referenzen verwaltet werden müssen, wie erklärt hier
Viele der Antworten geben einige gute Informationen, aber die Antwort ist nicht vollständig.
Die Frage fragt nach der Weitergabe von Informationen zwischen View-Controllern. In diesem speziellen Beispiel wird nach dem Weitergeben von Informationen zwischen Ansichten gefragt. Angesichts der neuen Selbstverständlichkeit von iOS war das ursprüngliche Poster jedoch wahrscheinlich für die Ansicht zwischen ViewControllern und nicht zwischen Ansichten (ohne Beteiligung der ViewControllers) gemeint. Es scheint, dass sich alle Antworten auf zwei Ansichtscontroller konzentrieren, aber was ist, wenn die App mehr als zwei Ansichtscontroller in den Informationsaustausch einbeziehen muss?
Das ursprüngliche Poster fragte auch nach Singletons und der Verwendung von AppDelegate. Diese Fragen müssen beantwortet werden.
Um allen anderen Personen zu helfen, die sich diese Frage ansehen und eine vollständige Antwort wünschen, werde ich versuchen, sie zu beantworten.
Anwendungsszenarien
Anstatt eine höchst hypothetische, abstrakte Diskussion zu führen, hilft es, konkrete Anwendungen im Auge zu behalten. Um bei der Definition einer Situation mit zwei Ansichten und einer Situation mit mehr als zwei Ansichten zu helfen, werde ich zwei konkrete Anwendungsszenarien definieren.
Szenario 1: Maximal zwei View-Controller müssen Informationen gemeinsam nutzen. __ Siehe Diagramm eins.
In der Anwendung gibt es zwei Ansichtscontroller. Es gibt ein ViewControllerA (Dateneingabeformular) und View Controller B (Produktliste). Die in der Produktliste ausgewählten Artikel müssen mit den im Textfeld des Dateneingabeformulars angezeigten Elementen übereinstimmen. In diesem Szenario müssen ViewControllerA und ViewControllerB direkt miteinander und mit keinen anderen View-Controllern kommunizieren.
Szenario zwei: Mehr als zwei Ansichtssteuerungen müssen die gleichen Informationen gemeinsam nutzen. _ Siehe Diagramm zwei.
In der Anwendung gibt es vier Ansichtscontroller. Es ist eine tabulatorbasierte Anwendung zum Verwalten des Home-Inventars. Drei Ansichtscontroller bieten unterschiedlich gefilterte Ansichten derselben Daten:
Jedes Mal, wenn ein einzelnes Element erstellt oder bearbeitet wird, muss es auch mit den anderen View-Controllern synchronisiert werden. Wenn wir beispielsweise ein Boot in ViewControllerD hinzufügen, aber noch nicht versichert sind, muss das Boot erscheinen, wenn der Benutzer zu ViewControllerA (Luxury Items) und auch ViewControllerC (Entire Home Inventory) wechselt, jedoch nicht, wenn der Benutzer zu geht ViewControllerB (Nicht versicherte Gegenstände). Wir müssen uns nicht nur um das Hinzufügen neuer Elemente kümmern, sondern auch um das Löschen von Elementen (die möglicherweise von einem der vier Ansichtscontroller aus zulässig sind) oder das Bearbeiten vorhandener Elemente (die möglicherweise über das "Formular zum Hinzufügen neuer Elemente" zulässig sind) zur Bearbeitung).
Da alle View-Controller dieselben Daten gemeinsam nutzen müssen, müssen alle vier View-Controller synchron bleiben. Daher muss eine Kommunikation mit allen anderen View-Controllern hergestellt werden, wenn ein einzelner View-Controller die zugrunde liegenden Daten ändert. Es sollte offensichtlich sein, dass in diesem Szenario nicht jeder View Controller direkt mit jedem anderen View Controller kommunizieren soll. Falls es nicht offensichtlich ist, überlegen Sie, ob wir 20 verschiedene Ansichtscontroller hätten (anstatt nur 4). Wie schwierig und fehleranfällig wäre es, jeden der anderen 19 View-Controller zu benachrichtigen, wenn ein View-Controller eine Änderung vornimmt?
Die Lösungen: Delegierte und das Observer Pattern und Singletons
Im ersten Szenario haben wir mehrere praktikable Lösungen, wie andere Antworten gegeben haben
Im zweiten Szenario haben wir andere praktikable Lösungen:
Ein singleton ist eine Instanz einer Klasse. Diese Instanz ist die einzige Instanz, die während ihrer Lebensdauer existiert. Ein Singleton erhält seinen Namen von der Tatsache, dass es sich um eine einzelne Instanz handelt. Normalerweise haben Entwickler, die Singletons verwenden, spezielle Klassenmethoden, um auf sie zuzugreifen.
+ (HouseholdInventoryManager*) sharedManager; {
static dispatch_once_t onceQueue;
static HouseholdInventoryManager* _sharedInstance;
// dispatch_once is guaranteed to only be executed once in the
// lifetime of the application
dispatch_once(&onceQueue, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
Nun, da wir verstehen, was ein Singleton ist, wollen wir diskutieren, wie ein Singleton in das Beobachtermuster passt. Das Beobachtermuster wird für ein Objekt verwendet, um auf Änderungen eines anderen Objekts zu reagieren. Im zweiten Szenario haben wir vier verschiedene View-Controller, die alle über Änderungen an den zugrunde liegenden Daten erfahren möchten. Die "zugrunde liegenden Daten" sollten zu einer einzelnen Instanz gehören, einem Singleton. Das "Wissen über Änderungen" wird durch das Beobachten von Änderungen erreicht, die am Singleton vorgenommen wurden.Die Home-Inventaranwendung verfügt über eine einzige Instanz einer Klasse, die zum Verwalten einer Liste von Inventarelementen vorgesehen ist. Der Manager würde eine Sammlung von Haushaltsgegenständen verwalten. Folgendes ist eine Klassendefinition für den Datenmanager:.
#import <Foundation/Foundation.h>
@class JGCHouseholdInventoryItem;
@interface HouseholdInventoryManager : NSObject
/*!
The global singleton for accessing application data
*/
+ (HouseholdInventoryManager*) sharedManager;
- (NSArray *) entireHouseholdInventory;
- (NSArray *) luxuryItems;
- (NSArray *) nonInsuredItems;
- (void) addHouseholdItemToHomeInventory:(JGCHouseholdInventoryItem*)item;
- (void) editHouseholdItemInHomeInventory:(JGCHouseholdInventoryItem*)item;
- (void) deleteHoueholdItemFromHomeInventory:(JGCHouseholdInventoryItem*)item;
@end
Viele Einsteigerprogrammierer nutzen die Tatsache, dass es während der gesamten Laufzeit der Anwendung immer genau einen Application Delegate gibt, auf den global zugegriffen werden kann. Anfängliche Programmierer nutzen diese Tatsache, um Objekte und Funktionen in appDelegate zu packen, um von überall aus der Anwendung darauf zugreifen zu können. Nur weil AppDelegate ein Singleton ist, bedeutet das nicht, dass es alle anderen Singletons ersetzen sollte. Dies ist eine schlechte Praxis, da sie eine Klasse zu stark belastet und gegen objektorientierte Praktiken verstößt. Jede Klasse sollte eine klare Rolle haben, die leicht zu erklären ist, oft nur durch den Namen der Klasse.
Jedes Mal, wenn Ihr Anwendungsdelegat aufgebläht wird, müssen Sie die Funktionalität in Singletons entfernen. Der Core Data Stack sollte beispielsweise nicht im AppDelegate belassen werden, sondern sollte in seiner eigenen Klasse, der coreDataManager-Klasse, abgelegt werden.
Verweise
Das Zurückgeben von Daten von ViewController 2(destination) an ViewController 1(Source) ist die interessantere Sache.
Das wurde hier schon besprochen.
Ich fand, dass es mehr Möglichkeiten gibt:
-Verwendung von blockbacks:
verwenden Sie es in der prepareForSegue
-Methode im VC1
NextViewController *destinationVC = (NextViewController *) segue.destinationViewController;
[destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC)
{
self.blockLabel.text = destination.blockTextField.text;
}];
-Verwendung von Storyboards Abwickeln (Beenden)
Implementieren Sie eine Methode mit einem UIStoryboardSegue-Argument in VC 1 wie dieser:
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue { }
Hängen Sie im Storyboard die Schaltfläche "Zurück" an die grüne Schaltfläche "Beenden " (Abwickeln) des Vc . Jetzt haben Sie ein Segment, das "zurückgeht", so dass Sie die DestinationViewController -Eigenschaft in prepareForSegue von VC2 verwenden können und jede Eigenschaft von VC1.
Eine weitere Möglichkeit, Storyboards zu verwenden. Rückgängig machen (Beenden) - Sie können Die in VC1 beschriebene Methode verwenden
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
NextViewController *nextViewController = segue.sourceViewController;
self.unwindLabel.text = nextViewController.unwindPropertyPass;
}
Und in prepareForSegue von VC1 können Sie jede Eigenschaft ändern, die Sie freigeben möchten.
In beiden Abwickeloptionen können Sie die Tag-Eigenschaft der Schaltfläche festlegen und sie einchecken die prepareForSegue.
Ich hoffe, ich habe der Diskussion etwas hinzugefügt.
:) Prost.
Es gibt mehrere Methoden, um Daten gemeinsam zu nutzen.
Sie können Daten jederzeit mit NSUserDefaults
freigeben. Legen Sie den Wert fest, den Sie in Bezug auf einen Schlüssel Ihrer Wahl freigeben möchten, und rufen Sie den Wert von NSUserDefault
ab, der diesem Schlüssel im Controller der nächsten Ansicht zugeordnet ist.
[[NSUserDefaults standardUserDefaults] setValue:value forKey:key]
[[NSUserDefaults standardUserDefaults] objectForKey:key]
Sie können einfach eine Eigenschaft in viewcontrollerA
erstellen. Erstellen Sie ein Objekt von viewcontrollerA
in viewcontrollerB
und weisen Sie der Eigenschaft den gewünschten Wert zu.
Sie können auch benutzerdefinierte Delegaten dafür erstellen.
Das OP erwähnte zwar nicht die Ansichts-Controller, aber es gab so viele Antworten, dass ich mit einbeziehen wollte, was einige der neuen Funktionen der LLVM ermöglichen, dies zu vereinfachen, wenn Daten von einem Ansichts-Controller an einen anderen weitergegeben werden sollen einige Ergebnisse zurückbekommen.
Storyboard-Segmente, ARC- und LLVM-Blöcke machen dies für mich einfacher denn je. Bei einigen Antworten wurden bereits Storyboards und Abschnitte erwähnt, die sich jedoch immer noch auf Delegierung stützten. Das Definieren von Delegaten funktioniert zwar, aber es ist für manche Benutzer einfacher, Zeiger oder Codeblöcke zu übergeben.
Mit UINavigators und Segues gibt es einfache Möglichkeiten, Informationen an den untergeordneten Controller zu übergeben und die Informationen zurückzubekommen. ARC macht das Übergeben von Zeigern auf von NSObjects abgeleitete Dinge einfach. Wenn Sie möchten, dass der untergeordnete Controller einige Daten für Sie hinzufügt/ändert/ändert, übergeben Sie ihm einen Zeiger auf eine veränderliche Instanz. Blöcke erleichtern das Übergeben von Aktionen. Wenn Sie also möchten, dass der untergeordnete Controller eine Aktion auf Ihrem übergeordneten Controller auslöst, übergeben Sie einen Block. Sie definieren den Block, um eine beliebige Anzahl von Argumenten zu akzeptieren, die für Sie sinnvoll ist. Sie können die API auch so entwerfen, dass sie mehrere Blöcke verwendet, wenn dies besser passt.
Hier sind zwei triviale Beispiele für den Kleber. Der erste ist unkompliziert und zeigt einen für die Eingabe übergebenen Parameter, den zweiten für die Ausgabe.
// Prepare the destination view controller by passing it the input we want it to work on
// and the results we will look at when the user has navigated back to this controller's view.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[[segue destinationViewController]
// This parameter gives the next controller the data it works on.
segueHandoffWithInput:self.dataForNextController
// This parameter allows the next controller to pass back results
// by virtue of both controllers having a pointer to the same object.
andResults:self.resultsFromNextController];
}
Dieses zweite Beispiel zeigt, wie ein Rückmeldeblock für das zweite Argument übergeben wird. Ich mag die Verwendung von Blöcken, weil sie die relevanten Details in der Quelle - der übergeordneten Ebene - eng zusammenhält.
// Prepare the destination view controller by passing it the input we want it to work on
// and the callback when it has done its work.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[[segue destinationViewController]
// This parameter gives the next controller the data it works on.
segueHandoffWithInput:self.dataForNextController
// This parameter allows the next controller to pass back results.
resultsBlock:^(id results) {
// This callback could be as involved as you like.
// It can use Grand Central Dispatch to have work done on another thread for example.
[self setResultsFromNextController:results];
}];
}
Wenn Sie Daten von einem Controller an einen anderen übergeben möchten, probieren Sie diesen Code
FirstViewController.h
@property (nonatomic, retain) NSString *str;
SecondViewController.h
@property (nonatomic, retain) NSString *str1;
FirstViewController.m
- (void)viewDidLoad
{
// message for the second SecondViewController
self.str = @"text message";
[super viewDidLoad];
}
-(IBAction)ButtonClicked
{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
secondViewController.str1 = str;
[self.navigationController pushViewController:secondViewController animated:YES];
}
Ich habe lange nach dieser Lösung gesucht, Atlast habe ich gefunden. Zunächst deklarieren Sie alle Objekte in Ihrer SecondViewController.h-Datei wie
@interface SecondViewController: UIviewController
{
NSMutableArray *myAray;
CustomObject *object;
}
Weisen Sie jetzt in Ihrer Implementierungsdatei den Speicher für diese Objekte zu
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
myAray=[[NSMutableArray alloc] init];
object=[[CustomObject alloc] init];
}
return self;
}
Nun haben Sie den Speicher für Array
und Objekt zugewiesen. Jetzt können Sie diese Erinnerung füllen, bevor Sie diese ViewController
drücken.
Gehen Sie zu Ihrem SecondViewController.h und schreiben Sie zwei Methoden
-(void)setMyArray:(NSArray *)_myArray;
-(void)setMyObject:(CustomObject *)_myObject;
in der Implementierungsdatei können Sie die Funktion implementieren
-(void)setMyArray:(NSArray *)_myArray
{
[myArra addObjectsFromArray:_myArray];
}
-(void)setMyObject:(CustomObject *)_myObject
{
[object setCustomObject:_myObject];
}
sie erwarten, dass Ihre CustomObject
eine Setterfunktion haben muss.
jetzt ist deine grundlegende Arbeit erledigt. Gehen Sie zu der Stelle, an der Sie die Variable SecondViewController
drücken möchten, und führen Sie die folgenden Schritte aus
SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]] ;
[secondView setMyArray:ArrayToPass];
[secondView setMyObject:objectToPass];
[self.navigationController pushViewController:secondView animated:YES ];
Achten Sie auf Rechtschreibfehler.
Dies ist nicht die Art und Weise, dies zu tun. Sie sollten Delegaten verwenden. Ich nehme an, wir haben zwei View-Controller, ViewController1 und ViewController2. Diese Check-Sache befindet sich im ersten und wenn sich ihr Status ändert, möchten Sie etwas in ViewController2 tun Um dies auf die richtige Weise zu erreichen, sollten Sie Folgendes tun:
Fügen Sie Ihrem Projekt eine neue Datei hinzu (Objective-C-Protokoll) Datei -> Neu, nennen Sie sie jetzt ViewController1Delegate oder was immer Sie möchten, und schreiben Sie diese zwischen die Direktiven @interface und @end
@optional
- (void)checkStateDidChange:(BOOL)checked;
Gehen Sie jetzt zu ViewController2.h und fügen Sie hinzu
#import "ViewController1Delegate.h"
Ändern Sie dann die Definition in
@interface ViewController2: UIViewController<ViewController1Delegate>
Gehen Sie jetzt zu ViewController2.m und fügen Sie in der Implementierung Folgendes hinzu:
- (void)checkStateDidChange:(BOOL)checked {
if (checked) {
// Do whatever you want here
NSLog(@"Checked");
}
else {
// Also do whatever you want here
NSLog(@"Not checked");
}
}
Gehen Sie jetzt zu ViewController1.h und fügen Sie die folgende Eigenschaft hinzu:
@property (weak, nonatomic) id<ViewController1Delegate> delegate;
Wenn Sie nun nach einem Ereignis ViewController1 in ViewController2 erstellen, sollten Sie dies mit NIB-Dateien tun:
ViewController1* controller = [[NSBundle mainBundle] loadNibNamed:@"ViewController1" owner:self options:nil][0];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
Jetzt sind Sie fertig, wenn Sie das in ViewController1 geänderte Prüfereignis feststellen, müssen Sie nur noch das Folgende tun
[delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control
Bitte sagen Sie mir, wenn etwas nicht klar ist, wenn ich Ihre Frage nicht richtig verstanden habe.
Wenn Sie Daten von einem ViewController an einen anderen ViewController senden möchten, können Sie Folgendes tun:
Nehmen wir an, wir haben viewController: viewControllerA und viewControllerB
Jetzt in viewControllerB.h
@interface viewControllerB : UIViewController {
NSString *string;
NSArray *array;
}
- (id)initWithArray:(NSArray)a andString:(NSString)s;
In viewControllerB.m
#import "viewControllerB.h"
@implementation viewControllerB
- (id)initWithArray:(NSArray)a andString:(NSString)s {
array = [[NSArray alloc] init];
array = a;
string = [[NSString alloc] init];
string = s;
}
In viewControllerA.m
#import "viewControllerA.h"
#import "viewControllerB.h"
@implementation viewControllerA
- (void)someMethod {
someArray = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
someString = [NSString stringWithFormat:@"Hahahahaha"];
viewControllerB *vc = [[viewControllerB alloc] initWithArray:someArray andString:someString];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
So können Sie Daten von viewControllerA an viewControllerB übergeben, ohne einen Delegaten festzulegen. ;)
1. Erstellen Sie die Instanz des ersten View Controllers im zweiten View Controller und nehmen Sie ihre Eigenschaft @property (nonatomic,assign)
vor.
2. Weisen Sie die SecondviewController
-Instanz dieses View-Controllers zu.
2. Wenn Sie die Auswahl abgeschlossen haben, kopieren Sie das Array in den ersten View Controller. Wenn Sie das SecondView entladen, wird FirstView die Array-Daten speichern.
Hoffe das hilft.
Daten zwischen FirstViewController an SecondViewController weitergeben
Zum Beispiel:
FirstViewController String-Wert als
StrFirstValue = @"first";
so können wir diesen Wert in der zweiten Klasse mit dem folgenden Schritt übergeben
1> Wir müssen ein String-Objekt in der SecondViewController.h-Datei erstellen
NSString *strValue;
2> Die Eigenschaft muss wie unten in der .h-Datei angegeben deklariert werden
@property (strong, nonatomic) NSString *strSecondValue;
3> Synthetisieren Sie diesen Wert in der FirstViewController.m-Datei unterhalb der Header-Deklaration
@synthesize strValue;
und in FirstViewController.h:
@property (strong, nonatomic) NSString *strValue;
4> In FirstViewController, von welcher Methode wir zur zweiten Ansicht navigieren, schreiben Sie bitte den Code in dieser Methode.
SecondViewController *secondView= [[SecondViewController alloc]
initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]];
[secondView setStrSecondValue:StrFirstValue];
[self.navigationController pushViewController:secondView animated:YES ];
Zur Zeit arbeite ich an einer Open-Source-Lösung für dieses Problem durch ein Projekt namens MCViewFactory, das hier zu finden ist:
https://github.com/YetiHQ/manticore-iosviewfactory
Die Idee ist imitiert das Paradigma von Android, indem eine globale Fabrik verwendet wird, um zu verwalten, welche Ansicht Sie betrachten, und "Intents" verwendet, um Daten zwischen Ansichten zu wechseln und zu übergeben. Die gesamte Dokumentation befindet sich auf der Github-Seite. Hier einige Highlights:
Sie richten alle Ihre Ansichten in XIB-Dateien ein und registrieren sie beim App-Delegierten, während Sie die Factory initialisieren.
// Register activities
MCViewFactory *factory = [MCViewFactory sharedFactory];
// the following two lines are optional.
[factory registerView:@"YourSectionViewController"];
Wenn Sie jetzt in Ihrem VC zu einem neuen VC wechseln und Daten übergeben möchten, erstellen Sie eine neue Absicht und fügen Daten zu seinem Wörterbuch hinzu (SavedInstanceState). Dann legen Sie einfach die aktuelle Absicht der Fabrik fest:
MCIntent* intent = [MCIntent intentWithSectionName:@"YourSectionViewController"];
[intent setAnimationStyle:UIViewAnimationOptionTransitionFlipFromLeft];
[[intent savedInstanceState] setObject:@"someValue" forKey:@"yourKey"];
[[intent savedInstanceState] setObject:@"anotherValue" forKey:@"anotherKey"];
// ...
[[MCViewModel sharedModel] setCurrentSection:intent];
Alle Ihre diesbezüglichen Ansichten müssen Unterklassen von MCViewController sein, mit denen Sie die neue onResume: -Methode überschreiben können, um auf die übergebenen Daten zugreifen zu können.
-(void)onResume:(MCIntent *)intent {
NSObject* someValue = [intent.savedInstanceState objectForKey:@"yourKey"];
NSObject* anotherValue = [intent.savedInstanceState objectForKey:@"anotherKey"];
// ...
// ensure the following line is called, especially for MCSectionViewController
[super onResume:intent];
}
Ich hoffe, einige von Ihnen finden diese Lösung nützlich/interessant.
In meinem Fall habe ich eine Singleton-Klasse verwendet, die als globales Objekt arbeiten kann, um von fast überall in der App auf die Daten zuzugreifen. Als Erstes bauen Sie eine Singleton-Klasse. Lesen Sie bitte die Seite " Wie soll mein Objective-C-Singleton aussehen? " Und um das Objekt global zugänglich zu machen, importieren Sie es einfach in appName_Prefix.pch
, das für die Anwendung von import-Anweisungen in allen Klassen gilt Um auf dieses Objekt zuzugreifen und es zu verwenden, habe ich einfach eine Klassenmethode implementiert, um die gemeinsam genutzte Instanz zurückzugeben, die ihre eigenen Variablen enthält
Erstellen Sie die Eigenschaft in next view controller .h
und definieren Sie Getter und Setter.
Fügen Sie diesen property
in NextVC.h in nextVC hinzu
@property (strong, nonatomic) NSString *indexNumber;
Hinzufügen
@synthesize indexNumber;
in NextVC.m
Und zuletzt
NextVC *vc=[[NextVC alloc]init];
[email protected]"123";
[self.navigationController vc animated:YES];
Ich weiß, dass dies ein geschlagenes Thema ist, aber für diejenigen, die diese Frage mit einer schnellen Neigung beantworten möchten und ein einfaches Beispiel wollen, hier meine Methode zum Weiterleiten von Daten, wenn Sie einen Segue verwenden, um herumzukommen.
Es ist ähnlich wie oben, jedoch ohne die Knöpfe, Beschriftungen und dergleichen. Daten einfach von einer Ansicht zur nächsten weitergeben.
Das Storyboard einrichten
Es gibt drei Teile.
Dies ist ein sehr einfaches Ansichtslayout mit einem Abstand zwischen ihnen.
Hier ist das Setup für den Absender
Hier ist das Setup für den Empfänger.
Zuletzt das Setup für das Segment.
Die View Controller
Wir halten das so einfach, also keine Tasten, keine Aktionen, wir verschieben beim Laden der Anwendung einfach Daten vom Sender zum Empfänger und geben den übertragenen Wert an die Konsole aus.
Diese Seite nimmt den ursprünglich geladenen Wert und gibt ihn weiter.
//
// ViewControllerSender.Swift
// PassDataBetweenViews
//
// Created by Chris Cantley on 8/25/15.
// Copyright (c) 2015 Chris Cantley. All rights reserved.
//
import UIKit
class ViewControllerSender: UIViewController {
// THE STUFF - put some info into a variable
let favoriteMovie = "Ghost Busters"
override func viewDidAppear(animated: Bool) {
// PASS IDENTIFIER - go to the recieving view controller.
self.performSegueWithIdentifier("goToReciever", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//GET REFERENCE - ...to the receiver view.
var viewControllerReceiver = segue.destinationViewController as? ViewControllerReceiver
//PASS STUFF - pass the variable along to the target.
viewControllerReceiver!.yourFavMovie = self.favoriteMovie
}
}
Diese Seite sendet beim Laden nur den Wert der Variablen an die Konsole. Zu diesem Zeitpunkt sollte unser Lieblingsfilm in dieser Variablen sein.
//
// ViewControllerReceiver.Swift
// PassDataBetweenViews
//
// Created by Chris Cantley on 8/25/15.
// Copyright (c) 2015 Chris Cantley. All rights reserved.
//
import UIKit
class ViewControllerReceiver: UIViewController {
//Basic empty variable waiting for you to pass in your fantastic favorite movie.
var yourFavMovie = ""
override func viewDidLoad() {
super.viewDidLoad()
//And now we can view it in the console.
println("The Movie is \(self.yourFavMovie)")
}
}
So können Sie es angehen, wenn Sie ein Segment verwenden möchten und Ihre Seiten nicht unter einem Navigationscontroller liegen.
Sobald es ausgeführt wird, sollte es automatisch in die Empfängeransicht wechseln und den Wert vom Sender an den Empfänger übergeben, wobei der Wert in der Konsole angezeigt wird.
Die Delegierung ist die einzige Lösung, die solche Operationen ausführt, wenn Sie .xib-Dateien verwenden. Alle oben beschriebenen Antworten gelten jedoch für storyboard
für .xibs-Dateien, die Sie für die Delegierung benötigen. das ist nur Lösung, die du kannst.
Eine andere Lösung ist, Singleton-Klassenmuster zu verwenden, es einmal zu initialisieren und in Ihrer gesamten App zu verwenden.
wenn Sie Daten von ViewControlerOne an ViewControllerTwo übergeben möchten, probieren Sie diese ..
führen Sie diese in ViewControlerOne.h aus
@property (nonatomic, strong) NSString *str1;
tun Sie dies in ViewControllerTwo.h
@property (nonatomic, strong) NSString *str2;
Synthetisieren Sie str2 in ViewControllerTwo.m
@interface ViewControllerTwo ()
@end
@implementation ViewControllerTwo
@synthesize str2;
führen Sie diese in ViewControlerOne.m aus
- (void)viewDidLoad
{
[super viewDidLoad];
// Data or string you wants to pass in ViewControllerTwo..
self.str1 = @"hello world";
}
klicken Sie auf die Schaltflächen Ereignis klicken ..
-(IBAction)ButtonClicked
{ //Navigation on buttons click event from ViewControlerOne to ViewControlerTwo with transferring data or string..
ViewControllerTwo *objViewTwo=[self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerTwo"];
obj.str2=str1;
[self.navigationController pushViewController: objViewTwo animated:YES];
}
tun Sie dies in ViewControllerTwo.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%@",str2);
}
Es gibt unzählige Möglichkeiten, dies zu tun, und es ist wichtig, die richtige zu wählen. Eine der größten architektonischen Entscheidungen liegt wahrscheinlich darin, wie der Modellcode in der App gemeinsam genutzt oder darauf zugegriffen wird.
Ich habe vor einiger Zeit einen Blogbeitrag darüber geschrieben: Modellcode teilen . Hier eine kurze Zusammenfassung:
Ein Ansatz besteht darin, Zeiger auf die Modellobjekte zwischen Ansichtssteuerungen zu teilen.
Da die Vorbereitung für das Segue am häufigsten ist, ist hier ein Beispiel:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var next = segue.destinationViewController as NextViewController
next.dataSource = dataSource
}
Ein anderer Ansatz besteht darin, einen Bildschirm voller Daten gleichzeitig zu handhaben und anstatt die View-Controller miteinander zu koppeln, koppeln Sie jeden View-Controller mit einer einzelnen Datenquelle, zu der sie unabhängig voneinander gelangen können.
Die häufigste Art, wie ich das gesehen habe, ist eine Singleton -Instanz. Wenn Ihr Singleton-Objekt DataAccess
wäre, könnten Sie Folgendes in der viewDidLoad-Methode von UIViewController ausführen:
func viewDidLoad() {
super.viewDidLoad()
var data = dataAccess.requestData()
}
Es gibt Hinzufügungstools, die auch helfen, Daten weiterzugeben:
Das Schöne an Core Data ist, dass es inverse Beziehungen hat. Wenn Sie also nur einem NotesViewController das Notes-Objekt zuweisen möchten, können Sie dies tun, da es eine umgekehrte Beziehung zu etwas anderem wie dem Notizbuch hat. Wenn Sie Daten auf dem Notizbuch im NotesViewController benötigen, können Sie den Objektgraph mit den folgenden Schritten sichern:
let notebookName = note.notebook.name
Lesen Sie mehr dazu in meinem Blog-Beitrag: Modellcode teilen
NewsViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tbl_View deselectRowAtIndexPath:indexPath animated:YES];
News *newsObj = [newstitleArr objectAtIndex:indexPath.row];
NewsDetailViewController *newsDetailView = [[NewsDetailViewController alloc] initWithNibName:@"NewsDetailViewController" bundle:nil];
newsDetailView.newsHeadlineStr = newsObj.newsHeadline;
[self.navigationController pushViewController:newsDetailView animated:YES];
}
NewsDetailViewController.h
@interface NewsDetailViewController : UIViewController
@property(nonatomic,retain) NSString *newsHeadlineStr;
@end
NewsDetailViewController.m
@synthesize newsHeadlineStr;
Sie können Daten in App-Delegaten speichern, um über View-Controller in Ihrer Anwendung darauf zuzugreifen. Sie müssen lediglich eine freigegebene Instanz eines App-Delegaten erstellen
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
Zum Beispiel
wenn Sie einen NSArray object *arrayXYZ
angeben, können Sie in jedem View-Controller über appDelegate.arrayXYZ
darauf zugreifen.
Ich mag die Idee von Model-Objekten und Mock-Objekten auf der Basis von NSProxy, Daten zu übergeben oder zu verwerfen, wenn der Benutzer auswählt, dass er abgebrochen werden kann.
Es ist einfach, Daten zu übergeben, da es sich um ein einzelnes Objekt oder um mehrere Objekte handelt. Wenn Sie den UINavigationController-Controller angesprochen haben, können Sie die Referenz zum Modell im Inneren behalten, und alle übergebenen Ansichtscontroller können direkt vom Navigationscontroller darauf zugreifen.
Wenn Sie Daten von einem ViewController an einen anderen ViewController senden möchten, können Sie Folgendes tun:
Nehmen wir an, wir haben viewController: ViewController und NewViewController.
in ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4;
}
@property (nonatomic,retain) IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4;
-(IBAction)goToNextScreen:(id)sender;
@end
in ViewController.m
#import "ViewController.h"
#import "NewViewController.h"
@implementation ViewController
@synthesize mytext1,mytext2,mytext3,mytext4;
-(IBAction)goToNextScreen:(id)sender
{
NSArray *arr = [NSArray arrayWithObjects:mytext1.text,mytext2.text,mytext3.text,mytext4.text, nil];
NewViewController *newVc = [[NewViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
newVc.arrayList = arr;
[self.navigationController pushViewController:newVc animated:YES];
}
In NewViewController.h
#import <UIKit/UIKit.h>
@interface NewViewController : UITableViewController
{
NSArray *arrayList;
NSString *name,*age,*dob,*mobile;
}
@property(nonatomic, retain)NSArray *arrayList;
@end
In NewViewController.m
#import "NewViewController.h"
#import "ViewController.h"
@implementation NewViewController
@synthesize arrayList;
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [arrayList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [arrayList objectAtIndex:indexPath.row];
return cell;
}
@end
Auf diese Weise können wir die Daten von einem Viewcontroller an einen anderen Viewcontroller übergeben ...
Ich habe viele Leute gesehen, die dies mit der didSelectRowAtPath
-Methode verkompliziert haben. Ich verwende in meinem Beispiel Core Data.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//this solution is for using Core Data
YourCDEntityName * value = (YourCDEntityName *)[[self fetchedResultsController] objectAtIndexPath: indexPath];
YourSecondViewController * details = [self.storyboard instantiateViewControllerWithIdentifier:@"nameOfYourSecondVC"];//make sure in storyboards you give your second VC an identifier
//Make sure you declare your value in the second view controller
details.selectedValue = value;
//Now that you have said to pass value all you need to do is change views
[self.navigationController pushViewController: details animated:YES];
}
4 Zeilen Code in der Methode und Sie sind fertig.
Es gibt viele Antworten auf diese Fragen, die viele verschiedene Möglichkeiten bieten, um eine View Controller-Kommunikation durchzuführen, die tatsächlich funktionieren würde, aber ich sehe nirgendwo, welche davon am besten zu verwenden und welche zu vermeiden sind.
prepare(for:sender:)
-Methode von UIViewController
, wenn Sie ein Storyboard und Segmente verwendenObwohl diese Lösungen kurzfristig funktionieren, führen sie zu viele Abhängigkeiten ein, die die Architektur der App beeinträchtigen und später zu mehr Problemen führen werden.
Für Interessierte habe ich einige Artikel geschrieben, die sich eingehender mit diesen Punkten befassen und die verschiedenen Nachteile hervorheben:
Es gibt 3 Typen, um Daten von einem ViewController an einen anderen zu übergeben ViewController.
Demo-Projektlink hier - https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers
Demo-Projektlink hier - https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers
Swift 5
Die Antwort von Matt Price ist für die Weitergabe von Daten völlig in Ordnung, aber ich werde sie in der neuesten Swift-Version neu schreiben, da ich glaube, dass neue Programmierer es aufgrund der neuen Syntax und Methoden/Frameworks als schwierig empfinden, da sich der ursprüngliche Beitrag in Objective befindet -C.
Es gibt mehrere Optionen zum Übergeben von Daten zwischen Ansichts-Controllern.
Ich werde seine Logik in Swift mit dem neuesten iOS Framework umschreiben
Daten über den Navigationscontroller übertragen Drücken Sie : Von ViewControllerA zu ViewControllerB
Schritt 1. Variable in ViewControllerB deklarieren
var isSomethingEnabled = false
Schritt 2. Variable in ViewControllerB 'ViewDidLoad-Methode drucken
override func viewDidLoad() {
super.viewDidLoad()
//Print value received through segue, navigation Push
print("Value of 'isSomethingEnabled' from ViewControllerA : ", isSomethingEnabled)
}
Schritt 3. In ViewControllerA Übergeben Sie Daten, während Sie den Navigationscontroller durchlaufen
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
viewControllerB.isSomethingEnabled = true
if let navigator = navigationController {
navigator.pushViewController(viewControllerB, animated: true)
}
}
Hier ist der vollständige Code für:
ViewControllerA
import UIKit
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK:Passing Data through Navigation PushViewController
@IBAction func goToViewControllerB(_ sender: Any) {
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
viewControllerB.isSomethingEnabled = true
if let navigator = navigationController {
navigator.pushViewController(viewControllerB, animated: true)
}
}
}
}
ViewControllerB
import UIKit
class ViewControllerB: UIViewController {
//MARK: - Variable for Passing Data through Navigation Push
var isSomethingEnabled = false
override func viewDidLoad() {
super.viewDidLoad()
//Print value received through navigation Push
print("Value of 'isSomethingEnabled' from ViewControllerA : ", isSomethingEnabled)
}
}
Daten durch Segue leiten : von ViewControllerA zu ViewControllerB
Schritt 1. Erstelle einen Übergang von ViewControllerA zu ViewControllerB und gib Identifier = showDetailSegue im Storyboard ein, wie unten gezeigt
Schritt 2. In ViewControllerB Deklarieren Sie eine funktionsfähige Datei mit dem Namen isSomethingEnabled und geben Sie ihren Wert aus.
Schritt 3. In ViewControllerA übergeben Sie den Wert von isSomethingEnabled, während Sie Segue übergeben
Hier ist der vollständige Code für:
ViewControllerA
import UIKit
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK: - - Passing Data through Segue - -
@IBAction func goToViewControllerBUsingSegue(_ sender: Any) {
performSegue(withIdentifier: "showDetailSegue", sender: nil)
}
//Segue Delegate Method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "showDetailSegue") {
let controller = segue.destination as? ViewControllerB
controller?.isSomethingEnabled = true//passing data
}
}
}
ViewControllerB
import UIKit
class ViewControllerB: UIViewController {
var isSomethingEnabled = false
override func viewDidLoad() {
super.viewDidLoad()
//Print value received through segue
print("Value of 'isSomethingEnabled' from ViewControllerA : ", isSomethingEnabled)
}
}
Daten durch Delegaten übergeben : von ViewControllerB zu ViewControllerA
Schritt 1. Protokoll deklarierenViewControllerBDelegatein der ViewControllerB-Datei, jedoch außerhalb der Klasse
protocol ViewControllerBDelegate: NSObjectProtocol {
// Classes that adopt this protocol MUST define
// this method -- and hopefully do something in
// that definition.
func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?)
}
Schritt 2. Delegate-Variableninstanz in ViewControllerB deklarieren
var delegate: ViewControllerBDelegate?
Schritt 3. Daten für den Delegaten in der viewDidLoad-Methode von ViewControllerB senden
delegate?.addItemViewController(self, didFinishEnteringItem: "Data for ViewControllerA")
Schritt 4. Bestätigen Sie ViewControllerBDelegate in ViewControllerA
class ViewControllerA: UIViewController, ViewControllerBDelegate {
// to do
}
Schritt 5. Bestätigen Sie, dass Sie delegieren in ViewControllerA implementieren
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
viewControllerB.delegate = self//confirming delegate
if let navigator = navigationController {
navigator.pushViewController(viewControllerB, animated: true)
}
}
Schritt 6. Implementieren Sie die Delegate-Methode zum Empfangen von Daten in ViewControllerA
func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?) {
print("Value from ViewControllerB's Delegate", item!)
}
Hier ist der vollständige Code für:
ViewControllerA
import UIKit
class ViewControllerA: UIViewController, ViewControllerBDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
//Delegate method
func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?) {
print("Value from ViewControllerB's Delegate", item!)
}
@IBAction func goToViewControllerForDelegate(_ sender: Any) {
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
viewControllerB.delegate = self
if let navigator = navigationController {
navigator.pushViewController(viewControllerB, animated: true)
}
}
}
}
ViewControllerB
import UIKit
//Protocol decleare
protocol ViewControllerBDelegate: NSObjectProtocol {
// Classes that adopt this protocol MUST define
// this method -- and hopefully do something in
// that definition.
func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?)
}
class ViewControllerB: UIViewController {
var delegate: ViewControllerBDelegate?
override func viewDidLoad() {
super.viewDidLoad()
//MARK: - - - - Set Data for Passing Data through Delegate - - - - - -
delegate?.addItemViewController(self, didFinishEnteringItem: "Data for ViewControllerA")
}
}
Daten durch Notification Observer übergeben : Von ViewControllerB zu ViewControllerA
Schritt 1. Daten in Notification Observer in ViewControllerB festlegen und veröffentlichen
let objToBeSent = "Test Message from Notification"
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
Schritt 2. Fügen Sie Notification Observer in ViewControllerA hinzu
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
Schritt 3. Empfangen Sie den Benachrichtigungsdatenwert in ViewControllerA
@objc func methodOfReceivedNotification(notification: Notification) {
print("Value of notification : ", notification.object ?? "")
}
Hier ist der vollständige Code für:
ViewControllerA
import UIKit
class ViewControllerA: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
// add observer in controller(s) where you want to receive data
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
}
//MARK: Method for receiving Data through Post Notification
@objc func methodOfReceivedNotification(notification: Notification) {
print("Value of notification : ", notification.object ?? "")
}
}
ViewControllerB
import UIKit
class ViewControllerB: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//MARK:Set data for Passing Data through Post Notification
let objToBeSent = "Test Message from Notification"
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
}
}
Daten durch Block übergeben : von ViewControllerB zu ViewControllerA
Schritt 1. Deklarieren Sie den Block in ViewControllerB
var permissionCompletionBlock: ((Bool) -> ())? = {_ in}
Schritt 2. Setzen Sie die Daten in ViewControllerB in den Block
if authorizationCompletionBlock != nil
{
authorizationCompletionBlock!(true)
}
Schritt 3. Blockdaten in ViewControllerA empfangen
//Receiver Block
controller!.authorizationCompletionBlock = { isGranted in
print("Data received from Block is :", isGranted)
}
Hier ist der vollständige Code für:
ViewControllerA
import UIKit
class ViewControllerA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK:Method for receiving Data through Block
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "showDetailSegue") {
let controller = segue.destination as? ViewControllerB
controller?.isSomethingEnabled = true
//Receiver Block
controller!.authorizationCompletionBlock = { isGranted in
print("Data received from Block is :", isGranted)
}
}
}
}
ViewControllerB
import UIKit
class ViewControllerB: UIViewController {
//MARK:Variable for Passing Data through Block
var authorizationCompletionBlock:((Bool)->())? = {_ in}
override func viewDidLoad() {
super.viewDidLoad()
//MARK:Set data for Passing Data through Block
if authorizationCompletionBlock != nil
{
authorizationCompletionBlock!(true)
}
}
}
Eine vollständige Beispielanwendung finden Sie auf meinem GitHub. Bitte lassen Sie mich wissen, wenn Sie Fragen dazu haben.
Dies ist ein wirklich tolles Tutorial für jeden, der es will. Hier ist der Beispielcode:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"myIdentifer]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
myViewController *destViewController = segue.destinationViewController;
destViewController.name = [object objectAtIndex:indexPath.row];
}
}
VERWENDEN VON NOTIFICATION CENTER
let imageDataDict:[String: UIImage] = ["image": image]
// post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict)
// `default` is now a property, not a method call
// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)
// handle notification
func showSpinningWheel(_ notification: NSNotification) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
let imageDataDict:[String: UIImage] = ["image": image]
// post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict)
// `default` is now a property, not a method call
// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)
// handle notification
@objc func showSpinningWheel(_ notification: NSNotification) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
um die Daten von einem VC an einen anderen zu senden, verwenden Sie diesen einfachen Ansatz:
YourNextVC *nxtScr = (YourNextVC*)[self.storyboard instantiateViewControllerWithIdentifier:@"YourNextVC"];//Set this identifier from your storyboard
nxtScr.comingFrom = @"PreviousScreen"l
[self.navigationController nxtScr animated:YES];
nun, wir haben nur wenige Möglichkeiten, mit Delegierten-Systemen oder StoryboardSegue zu arbeiten
1- As working with setter and getter method like in viewController.h
@property (retain, nonatomic) NSString *str;
now, in viewController.m
@synthesize str;
here i have pdf url and segue to another viewController like this and pdfObject is my pdfModel basicilly is NSOBJECT class.
str =[NSString stringWithFormat:@"%@",pdfObject.objPath];
NSLog(@"pdfUrl :***: %@ :***:",pdfUrl);
[self performSegueWithIdentifier:@"programPDFViewController_segue" sender:self];
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"programPDFViewController_segue"]){
programPDFViewController *pdfVC = [segue destinationViewController];
[pdfVC setRecievedPdfUrl:str];
}
}
Nun habe ich erfolgreich meine PDF-URL-Zeichenfolge und andere ViewController erhalten und diese Zeichenfolge in Webview verwendet ...
2- Bei der Arbeit mit Delegaten wie diesem habe ich eine NSObject-Klasse von Dienstprogrammen, die meine Methoden dateFormatter, sharedInstance, EscapeWhiteSpaceCharacters, convertImageToGrayScale und weitere Methoden enthält, mit denen ich nun in utilities.h gearbeitet habe
in diesem Fall müssen Sie keine Variablen erstellen, wenn Sie Ihre Daten in einem anderen View-Controller einmal in einem anderen View-Controller analysieren müssen. und wieder verwendet
@interface Utilities : NSObject
Utilities.h
+(Utilities*)sharedInstance;
@property(nonatomic,retain)NSString* strUrl;
jetzt in utilities.m
@implementation utilities
+(utilities*)sharedInstance
{
static utilities* sharedObj = nil;
if (sharedObj == nil) {
sharedObj = [[utilities alloc] init];
}
return sharedObj;
}
now its done come to your firstViewController.m and call delegate
NSString*str =[NSString stringWithFormat:@"%@",pdfObject.objPath];
[Connection sharedInstance].strUrl=nil;
[Connection sharedInstance].strUrl=str;
Now go to you secondViewController.m directly use it without creating variable
in viewwillapear what i did
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[self webViewMethod:[Connection sharedInstance].strUrl];
}
-(void)WebViewMethod:(NSString)Url{
// working with webview enjoy coding :D
}
diese Delegiertenarbeit ist zuverlässig mit der Speicherverwaltung
Ich empfehle Blöcke/Verschlüsse und benutzerdefinierte Konstruktoren.
Angenommen, Sie müssen die Zeichenfolge von FirstViewController an SecondViewController übergeben.
Ihr erster View Controller.
class FirstViewController : UIViewController {
func moveToViewControllerB() {
let second_screen = SecondViewController.screen(string: "DATA TO PASS", call_back: {
[weak self] (updated_data) in
///This closure will be called by second view controller when it updates something
})
self.navigationController?.pushViewController(second_screen, animated: true)
}
}
Ihr zweiter View Controller
class SecondViewController : UIViewController {
var incoming_string : String?
var call_back : ((String) -> Void)?
class func screen(string: String?, call_back : ((String) -> Void)?) -> SecondViewController {
let me = SecondViewController(nibName: String(describing: self), bundle: Bundle.main);
me.incoming_string = string
me.call_back = call_back
return me
}
// Suppose its called when you have to update FirstViewController with new data.
func updatedSomething() {
//Executing block that is implemented/assigned by the FirstViewController.
self.call_back?("UPDATED DATA")
}
}
Sie können Push-Segue vom Quell-Viewcontroller zum Ziel-Viewcontroller erstellen und den Bezeichnernamen wie folgt angeben .
Sie müssen dies mit didselectRowAt durchführen.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segue", sender: self)
}
Sie können das Array des ausgewählten Elements mit der folgenden Funktion übergeben.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = CategorytableView.indexPathForSelectedRow
let indexNumber = index?.row
print(indexNumber!)
let VC = segue.destination as! AddTransactionVC
VC.val = CategoryData[indexNumber!] . //You can pass here entire array instead of array element.
}
Und Sie müssen den Wert in viewdidload des Ziel-Viewcontrollers prüfen und dann in der Datenbank speichern.
override func viewDidLoad{
if val != ""{
btnSelectCategory.setTitle(val, for: .normal)
}
}
Ich bevorzuge es, es ohne Delegierte und Abteilungen zu machen. Dies kann mit benutzerdefiniertem Init oder durch Festlegen optionaler Werte erfolgen.
1. Benutzerdefinierte init
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
print(success)
})
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
private let completionClosure: ((Bool) -> Void)
init(string: String, completionClosure: ((Bool) -> Void)) {
self.completionClosure = completionClosure
super.init(nibName: nil, bundle: nil)
title = string
}
func finishWork() {
completionClosure()
}
}
2. Optionale Variablen
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB()
viewController.string = "Blabla"
viewController.completionClosure = { success in
print(success)
}
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
var string: String? {
didSet {
title = string
}
}
var completionClosure: ((Bool) -> Void)?
func finishWork() {
completionClosure?()
}
}
Eine Methode von Apple, dies zu tun, ist die Verwendung von Segues . Sie müssen die Funktion prepareForSegue () verwenden
Es gibt viele tolle Tutorials, hier ist eines: https://www.iphonelife.com/content/unleash-your-inner-app-developer-part-21-passing-data-between-controller
Lesen Sie auch die Apple-Dokumente zur Verwendung von Segues: https://developer.Apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html
Einfacher geht es hier nicht.
Verwenden Sie einfach eine globale Variable. Deklarieren Sie das Objekt oder die Variable, die für die Übergabe an die nächste Klasse erforderlich sind.
Zum Beispiel haben wir 2 Klassen - classA
und classB
.
In classA
enthält normalerweise:
#import "classA.h"
@interface classA()
@end
@implementation classA
-(void)viewDidLoad
{
...
}
-(void)didReceiveMemoryWarning
{
...
}
und classB
enthält:
#import "classB.h"
@interface classB()
@end
@implementation classB
-(void)viewWillLoad
{
...
}
-(void)didReceiveMemoryWarning
{
...
}
Importieren Sie nun die zweite Klasse classB
nach classA
#import "classA.h"
#import "classB.h" //---import classB to classA.
@interface classA()
@end
@implementation classA
-(void)viewDidLoad
{
...
}
-(void)didReceiveMemoryWarning
{
...
}
Jetzt haben wir eine Brücke, über die wir zur zweiten Klasse classB
gehen können. Um eine Variable oder ein Objekt als global zu deklarieren, deklarieren Sie es in der .m-Datei der ersten Klasse wie folgt
Im classA.h
#import "classA.h"
#import "classB.h"
@interface classA()
@end
NSString *temp; //----declare any object/variable as global.
@implementation classA
-(void)viewDidLoad
{
...
[email protected]"Hello";
...
}
-(void)didReceiveMemoryWarning
{
...
}
Hier ist das Objekt temp
ein globales Objekt der Klasse NSString
für den Zugriff auf das globale Objekt oder die globale Variable in einer beliebigen Klasse, deklarieren Sie einfach das Objekt oder die Variable in der zweiten Klasse neu. Z.B. unten angegeben:
Im classB.m
#import "classB.h"
@interface classB()
@end
extern NSString *temp; //----use `extern` keyword for using the global object/variable in classB that was declared in classA.
@implementation classB
-(void)viewDidLoad
{
...
LabeL.text=temp;
...
}
-(void)didReceiveMemoryWarning
{
...
}
Jetzt kann die zweite Klasse auf den Wert zugreifen. Einfach! .. Diese Methode kann für eine beliebige Anzahl von Klassen angewendet werden.
Anmerkung:
Sie sollten die .h-Datei der zweiten Klasse in die erste Klasse importieren. Es ist jedoch nicht erforderlich, die .h-Datei der ersten Klasse in die zweite Klasse zu importieren.
Erinnern Sie sich an die Brücke, wenn es eine Brücke gibt, sollte sie auf beiden Seiten gehen können.
Ich denke, das wird helfen. Es hat mir geholfen, als ich in der gleichen Situation war.
Sie müssen beim Erstellen von Apps für iOS immer das MVC-Konzept beachten. Es gibt zwei Szenarien, in denen Sie Daten von einem ViewController an einen anderen übergeben möchten:
Wenn sich in der Hierarchie ein "A" ViewContoller befindet und Sie einige Daten an "B" senden möchten, ist dies der next viewcontroller. In diesem Fall müssen Sie Segue verwenden. Legen Sie einfach einen Bezeichner für das Segment fest und schreiben Sie dann im VC "A" den folgenden Code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "A to B segue identifier" {
let bViewController = segue.destination as! UIDocumentBrowserViewController
bViewController.data = someData
}
}
Wenn es eine A
gibt, die B
als modal (oder eingebettet) auf sich geöffnet hat. Der B
viewcontroller sollte jetzt blind sein, was sein übergeordnetes Element betrifft. Die beste Methode, Daten an A
zurückzusenden, ist die Verwendung von Delegation
. Erstellen Sie ein Delegatenprotokoll im B
viewcontroller und eine delegate
-Eigenschaft. Also wird B
an ihren Delegierten berichten (Daten zurücksenden). Im A
viewcontroller implementieren wir das Delegate-Protokoll des B
viewcontroller und setzen self
als delegate
-Eigenschaft von B
viewcontroller in der prepare(forSegue:)
-Methode.
So sollte es richtig implementiert werden. Ich hoffe es hilft