Przekazywanie danych między kontrolerami widoku

Jestem nowy w iOS i Objective-C i całym paradygmacie MVC i utknąłem z następującym:

Mam widok, który działa jak formularz wprowadzania danych i chcę dać użytkownikowi możliwość wyboru wielu produktów. Produkty są wyświetlane w innym widoku z UITableViewController i włączyłem wiele zaznaczenia.

Moje pytanie brzmi, Jak mogę przenieść dane z jednego widoku do drugiego? Będę trzymał selekcje na UITableView w tablicy, ale jak przekazać to z powrotem do poprzedni widok formularza wprowadzania danych, dzięki czemu można go zapisać wraz z innymi danymi do podstawowych danych po złożeniu formularza?

Surfowałem i widziałem, jak niektórzy ludzie deklarują tablicę w delegacie aplikacji. Czytałem coś o Singletonach, ale nie rozumiem, co to jest i czytałem coś o tworzeniu modelu danych.

Jaki byłby właściwy sposób wykonania tego i jak bym to zrobił?

Author: Tamás Sengel, 2011-03-06

30 answers

To pytanie wydaje się być bardzo popularne tutaj na stackoverflow, więc pomyślałem, że spróbuję dać lepszą odpowiedź, aby pomóc ludziom zaczynającym w świecie iOS, takim jak ja.

Mam nadzieję, że ta odpowiedź jest wystarczająco jasna dla ludzi, aby zrozumieć i że niczego nie przeoczyłem.

Przekazywanie Danych Do Przodu

Przekazywanie danych do kontrolera widoku z innego kontrolera widoku. Użyjesz tej metody, jeśli chcesz przekazać obiekt / wartość z jednego widoku kontroler do innego kontrolera widoku, który może być przesuwany do stosu nawigacji.

W tym przykładzie będziemy mieli ViewControllerA i ViewControllerB

Aby przekazać BOOL wartość z ViewControllerA do ViewControllerB wykonamy następujące czynności.

  1. W ViewControllerB.h Utwórz właściwość dla BOOL

    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. W ViewControllerA musisz powiedzieć o ViewControllerB więc użyj

    #import "ViewControllerB.h"
    

    Następnie gdzie chcesz załadować widok np. didSelectRowAtIndex lub jakieś IBAction musisz ustawić właściwość w ViewControllerB przed wepchnięciem jej na stos nav.

    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];
    

    To ustawi isSomethingEnabled w ViewControllerB na BOOL wartość YES.

Przekazywanie danych do przodu za pomocą Segues

Jeśli używasz Storyboardów, najprawdopodobniej używasz segue i będziesz potrzebował tej procedury, aby przekazać dane do przodu. Jest to podobne do powyższego, ale zamiast przekazywać dane przed naciśnięciem kontrolera widoku, używasz metody o nazwie

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

Więc zdać BOOL z ViewControllerA do ViewControllerB wykonamy:

  1. W ViewControllerB.h Utwórz właściwość dla BOOL

    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. W ViewControllerA musisz powiedzieć o ViewControllerB więc użyj

    #import "ViewControllerB.h"
    
  3. Utwórz segue od ViewControllerA do ViewControllerB na storyboardzie i nadaj mu identyfikator, w tym przykładzie nazwiemy go "showDetailSegue"

  4. Następnie musimy dodać do ViewControllerA metodę, która jest wywoływana, gdy wykonuje się dowolny segue, z tego powodu musimy wykryć który został nazwany segue, a następnie coś zrobić. W naszym przykładzie sprawdzimy dla "showDetailSegue" i jeśli to zostanie wykonane, przekażemy naszą wartość BOOL do ViewControllerB

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

    Jeśli masz swoje widoki osadzone w kontrolerze nawigacyjnym, musisz nieco zmienić powyższą metodę na następującą

    -(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;
        }
    }
    

    To ustawi isSomethingEnabled w ViewControllerB na BOOL wartość YES.

Przekazywanie Danych Z Powrotem

Aby przekazać dane z ViewControllerB do ViewControllerA należy użyć protokoły i Delegaty lub bloki , te ostatnie mogą być używane jako luźno sprzężony mechanizm wywołań zwrotnych.

W tym celu uczynimy ViewControllerA delegatem ViewControllerB. Pozwala to ViewControllerB wysłać wiadomość z powrotem do ViewControllerA umożliwiając nam odesłanie danych.

Aby ViewControllerA być delegatem ViewControllerB musi on być zgodny z protokołem ViewControllerB, który musimy określić. To mówi ViewControllerA jakie metody musi zaimplementować.

  1. W ViewControllerB.h, poniżej #import, ale powyżej @interface określasz protokół.

    @class ViewControllerB;
    
    @protocol ViewControllerBDelegate <NSObject>
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
    @end
    
  2. Następnie w ViewControllerB.h musisz skonfigurować właściwość delegate i zsyntetyzować w ViewControllerB.m

    @property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
    
  3. W ViewControllerB wywołujemy wiadomość na delegate, gdy otwieramy kontroler widoku.

    NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
    
  4. To wszystko na ViewControllerB. Teraz w ViewControllerA.h, powiedz ViewControllerA, Aby zaimportować ViewControllerB i dostosować się do jego protokołu.

    #import "ViewControllerB.h"
    
    @interface ViewControllerA : UIViewController <ViewControllerBDelegate>
    
  5. W ViewControllerA.m zaimplementuj następującą metodę z naszego protokół

    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
    {
        NSLog(@"This was returned from ViewControllerB %@",item);
    }
    
  6. Przed wciśnięciem viewControllerB do stosu nawigacyjnego musimy powiedzieć ViewControllerB, że ViewControllerA jest jego delegatem, w przeciwnym razie otrzymamy błąd.

    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.delegate = self
    [[self navigationController] pushViewController:viewControllerB animated:YES];
    

Referencje

 1572
Author: Matt Price,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 20:46:14

Swift

Istnieje mnóstwo i Tony wyjaśnień tutaj i wokół StackOverflow, ale jeśli jesteś początkujący po prostu próbuje dostać coś podstawowego do pracy, spróbuj obejrzeć ten samouczek YouTube (to, co pomogło mi w końcu zrozumieć, jak to zrobić).

Przekazywanie danych do kontrolera następnego widoku

Poniżej znajduje się przykład oparty na filmie. Chodzi o to, aby przejść ciąg znaków z pola tekstowego w kontrolerze pierwszego widoku do etykiety w kontrolerze drugiego widoku.

Tutaj wpisz opis obrazka

Utwórz układ storyboard w Kreatorze interfejsów. Aby dokonać segue, po prostu Control kliknij na przycisk i przeciągnij do drugiego kontrolera widoku.

Kontroler Pierwszego Widoku

Kod pierwszego kontrolera widoku to

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!
    }

}

Kontroler Drugiego Widoku

I Kod dla drugiego kontrolera widoku jest

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
    }

}

Nie zapomnij

  • podłącz gniazda do UITextField i UILabel.
  • Ustaw Kontrolery pierwszego i drugiego widoku na odpowiednie pliki Swift w IB.

Przekazywanie danych z powrotem do poprzedniego kontrolera widoku

Aby przekazać dane z drugiego kontrolera widoku do pierwszego kontrolera, używasz protokołu i delegata. Ten filmik jest bardzo czytelny proces:

Poniżej znajduje się przykład oparty na filmie (z kilkoma modyfikacjami).

Tutaj wpisz opis obrazka

Utwórz układ storyboard w Kreatorze interfejsów. Ponownie, aby zrobić segue, po prostu Control przeciągnij z przycisku do drugiego widoku Kontroler. Ustaw identyfikator segue na showSecondViewController. Nie zapomnij również podłączyć gniazd i akcji za pomocą nazw podanych w poniższym kodzie.

Kontroler Pierwszego Widoku

Kod pierwszego kontrolera widoku to

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
    }
}

Zwróć uwagę na użycie naszego niestandardowego protokołu DataEnteredDelegate.

Kontroler drugiego widoku i protokół

Kod drugiego kontrolera widoku to

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)
    }
}

Zauważ, że protocol znajduje się poza kontrolerem widoku klasy.

To jest to. Uruchamiając aplikację teraz powinieneś być w stanie wysłać dane z drugiego kontrolera widoku do pierwszego.

 141
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 14:03:43

M W MVC jest dla "modelu", a w paradygmacie MVC rolą klas modeli jest zarządzanie danymi programu. Model jest przeciwieństwem widoku-widok wie, jak wyświetlać dane, ale nie wie nic o tym, co robić z danymi, podczas gdy model wie wszystko o tym, jak pracować z danymi, ale nic o tym, jak je wyświetlać. Modele mogą być skomplikowane , ale nie muszą być-model dla Twojej aplikacji może być tak prosty, jak tablica ciągów lub słowników.

Rola a kontroler ma pośredniczyć między widokiem a modelem. Dlatego potrzebują odniesienia do jednego lub więcej obiektów widoku i jednego lub więcej obiektów modelu. Załóżmy, że twój model jest tablicą słowników, a każdy słownik reprezentuje jeden wiersz w tabeli. Widok główny aplikacji wyświetla tę tabelę i może być odpowiedzialny za ładowanie tablicy z pliku. Gdy użytkownik zdecyduje się dodać nowy wiersz do tabeli, dotknie jakiegoś przycisku, a kontroler utworzy nowy (zmienny) słownik i dodaje go do tablicy. Aby wypełnić wiersz, kontroler tworzy kontroler widoku szczegółowego i nadaje mu nowy słownik. Kontroler widoku szczegółów wypełnia słownik i powraca. Słownik jest już częścią modelu, więc nic więcej nie musi się wydarzyć.

 119
Author: Caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 14:11:12

Istnieją różne sposoby, za pomocą których dane mogą być odbierane do innej klasy w systemie iOS. Na przykład -

  1. bezpośrednia inicjalizacja po przydzieleniu innej klasy.
  2. Delegacja-do przekazywania danych z powrotem
  3. Notification - dla transmisji danych do wielu klas w tym samym czasie
  4. zapisywanie w NSUserDefaults - do późniejszego dostępu
  5. klasy Singleton
  6. bazy danych i inne mechanizmy przechowywania jak plist, itp.

Ale dla prosty scenariusz przekazywania wartości do innej klasy, której alokacja odbywa się w bieżącej klasie, najczęstszą i preferowaną metodą byłoby bezpośrednie ustawienie wartości po alokacji. Odbywa się to w następujący sposób: -

Możemy to zrozumieć za pomocą dwóch kontrolerów - Controller1 i Controller2

Załóżmy, że w klasie Controller1 chcesz utworzyć obiekt Controller2 i wypchnąć go z przekazaną wartością łańcuchową. Można to zrobić tak: -

- (void)pushToController2 {

    Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
    [obj passValue:@"String"];
    [self pushViewController:obj animated:YES];
}

W Implementacja klasy Controller2 będzie taka funkcja jak -

@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

Możesz również bezpośrednio ustawić właściwości klasy Controller2 w podobny sposób jak to:

- (void)pushToController2 {

    Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
    [obj setStringPassed:@"String"];  
    [self pushViewController:obj animated:YES];
}

Aby przekazać wiele wartości, możesz użyć wielu parametrów, takich jak:-

Controller2 *obj = [[Controller2 alloc] initWithNib:@"Controller2" bundle:nil];
[obj passValue:@“String1” andValues:objArray withDate:date]; 

Lub jeśli chcesz przekazać więcej niż 3 parametry, które są związane ze wspólną cechą, możesz zapisać wartości do klasy modelu i przekazać ten modelObject do następnej klasy

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];

Tak w skrócie, jeśli chcesz -

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.

Hope this helps

 85
Author: borncrazy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-09 09:39:10

Po dalszych badaniach wydawało się, że protokoły i delegaci są poprawnym / preferowanym przez Apple sposobem na to.

I ended up using this example

Udostępnianie danych pomiędzy kontrolerami widoku i innymi obiektami @ iPhone dev SDK

Działało dobrze i pozwoliło mi przekazać ciąg i tablicę do przodu i do tyłu między moimi widokami.

Thanks for all your help

 74
Author: Matt Price,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-03 20:23:11

Znajduję najprostszą i najbardziej elegancką wersję z przechodzącymi blokami. Nazwijmy kontroler widoku, który czeka na zwrócone dane jako "A", A kontroler widoku jako"B". W tym przykładzie chcemy uzyskać 2 wartości: pierwsza z Type1 i druga z Type2.

Zakładając, że użyjemy storyboardu, pierwszy kontroler ustawia blok zwrotny, na przykład podczas przygotowania segue ' a:

- (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);
        };

    }
}

I kontroler widoku "B" powinien zadeklarować właściwość callback, BViewController.h:

// it is important to use "copy"
@property (copy) void(^callback)(Type1 *value1, Type2 *value2);

Niż w realizacji plik BViewController.m po tym, jak mamy pożądane wartości, aby zwrócić nasze wywołanie zwrotne powinno być wywołane:

if (self.callback)
    self.callback(value1, value2);

Należy pamiętać, że używanie bloku często wymaga zarządzania silnymi i _ _ słabymi referencjami, jak wyjaśniono tutaj

 59
Author: Leszek Zarna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-24 20:03:22

W wielu udzielonych odpowiedziach jest kilka dobrych informacji, ale żadna nie odnosi się do pytania w pełni.

Pytanie dotyczy przekazywania informacji pomiędzy kontrolerami widoku. Podany przykład dotyczy przekazywania informacji między widokami, ale biorąc pod uwagę samoistną nowość dla iOS, oryginalny plakat prawdopodobnie oznaczał między kontrolerami viewcontrollerów, a nie między widokami (bez żadnego udziału kontrolerów Viewcontrollerów). Wydaje się, że wszystkie odpowiedzi skupiają się na dwóch kontrolerach widoku, ale co czy aplikacja wymaga zaangażowania więcej niż dwóch kontrolerów widoku w wymianę informacji?

Oryginalny plakat pytał również oSingletony i użycieAppDelegate . Na te pytania należy odpowiedzieć.

Aby pomóc każdemu, kto patrzy na to pytanie, kto chce pełnej odpowiedzi, postaram się ją udzielić.

Scenariusze Aplikacji

Zamiast prowadzić wysoce hipotetyczną, abstrakcyjną dyskusję, pomaga mieć konkretne zastosowania w umyśle. Aby pomóc w zdefiniowaniu sytuacji z dwoma widokami i sytuacji z więcej niż dwoma widokami, zdefiniuję dwa konkretne scenariusze aplikacji.

Scenariusz pierwszy: maksymalnie dwa kontrolery widoku muszą udostępniać informacje. Patrz rysunek 1.

schemat problemu pierwotnego

W aplikacji znajdują się dwa kontrolery widoku. Istnieje ViewControllerA (formularz wprowadzania danych), oraz kontroler widoku B (lista produktów). Elementy wybrane na liście produktów musi pasować do pozycji wyświetlanych w polu tekstowym w formularzu wprowadzania danych. W tym scenariuszu ViewControllerA i ViewControllerB muszą komunikować się ze sobą bezpośrednio, bez żadnych innych kontrolerów widoku.

Scenariusz drugi: więcej niż dwa kontrolery widoku muszą udostępniać te same informacje. Patrz rysunek 2.

Strona główna inwentaryzacja schemat aplikacji

W aplikacji znajdują się cztery kontrolery widoku. Jest to aplikacja oparta na zakładkach do zarządzania zapasami w domu. Obecne są trzy Kontrolery widoku inaczej filtrowane widoki tych samych danych:

  • ViewControllerA-Przedmioty Luksusowe
  • ViewControllerB-przedmioty nieubezpieczone
  • ViewControllerC-Cały Spis Domowy
  • ViewControllerD-Dodaj Nowy Formularz Pozycji

Za każdym razem, gdy pojedynczy element jest tworzony lub edytowany, musi on również synchronizować się z innymi kontrolerami widoku. Na przykład, jeśli dodamy Łódź w ViewControllerD, ale nie jest jeszcze ubezpieczona, wtedy łódź musi się pojawić, gdy użytkownik przejdzie do ViewController (przedmioty luksusowe), a także ViewControllerC (cały spis domowy), ale nie wtedy, gdy użytkownik przechodzi do Viewcontrollerb (przedmioty nieubezpieczone). Musimy zająć się nie tylko dodawaniem nowych elementów, ale także usuwaniem elementów (które mogą być dozwolone z dowolnego z czterech kontrolerów widoku) lub edycją istniejących elementów (które mogą być dozwolone z "Add New Item Form", zmieniając to samo dla edycji).

Ponieważ wszystkie kontrolery widoku muszą współdzielić te same dane, wszystkie cztery widoki Kontrolery muszą pozostawać w synchronizacji, a zatem musi istnieć pewien rodzaj komunikacji ze wszystkimi innymi kontrolerami widoku, za każdym razem, gdy jeden kontroler widoku zmienia podstawowe dane. Powinno być dość oczywiste, że nie chcemy, aby każdy kontroler widoku komunikował się bezpośrednio ze sobą w tym scenariuszu. Jeśli nie jest to oczywiste, zastanów się, czy mieliśmy 20 różnych kontrolerów widoku (a nie tylko 4). Jak trudne i podatne na błędy byłoby powiadomienie każdego z pozostałych 19 kontrolerów widoku kiedykolwiek jeden kontroler widoku dokonał zmiany?

Rozwiązania: delegatów i obserwatora wzór, i Singletony

W scenariuszu pierwszym, mamy kilka realnych rozwiązań, jak inne odpowiedzi dały

  • segues
  • delegaci
  • Ustawianie właściwości kontrolerów widoku bezpośrednio
  • NSUserDefaults (właściwie kiepski wybór)

W drugim scenariuszu mamy inne realne rozwiązania:

  • Wzór Obserwatora
  • Singletony

A singleton jest instancją klasy, która jest jedyną instancją istniejącą w jej życiu. Singleton bierze swoją nazwę od tego, że jest pojedynczą instancją. Zwykle programiści, którzy używają singletonów, mają specjalne metody klasowe dostępu do nich.

+ (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;
}
Teraz, kiedy rozumiemy czym jest singleton, omówmy, jak singleton pasuje do wzoru obserwatora. Na wzorzec obserwatora jest używany dla jednego obiektu do reagowania na zmiany przez inny obiekt. W drugim scenariuszu mamy cztery różne kontrolery widoku, które chcą wiedzieć o zmianach w podstawowych danych. "Podstawowe dane" powinny należeć do pojedynczej instancji, singletonu. "Wiedzieć o zmianach" dokonuje się poprzez obserwację zmian dokonanych w singletonie.

Aplikacja home inventory będzie miała pojedynczą instancję klasy, która jest przeznaczona do zarządzania listą pozycji inwentaryzacyjnych. Kierownik zarządzałby kolekcją przedmiotów gospodarstwa domowego. Poniżej znajduje się definicja klasy dla Menedżera danych:

#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

Gdy kolekcja elementów inwentarza domowego ulegnie zmianie, Kontrolery widoku muszą zostać poinformowane o tej zmianie. Powyższa definicja klasy nie czyni oczywistym, jak to się stanie. Musimy podążać za wzorcem obserwatora. Kontrolery widoku muszą formalnie przestrzegać sharedmanagera. Istnieją dwa sposoby obserwacji innego obiekt:

  • Key-Value-Observing (KVO)
  • NSNotificationCenter.

W drugim scenariuszu nie mamy ani jednej właściwości Domaindinventorymanagera, którą można zaobserwować przy użyciu KVO. Ponieważ nie mamy jednej właściwości, która jest łatwo obserwowalna, wzorzec obserwatora, w tym przypadku, musi być zaimplementowany przy użyciu NSNotificationCenter. Każdy z czterech kontrolerów widoku subskrybuje powiadomienia, a sharedManager wysyła powiadomienia do Centrum powiadomień w razie potrzeby. Menedżer inwentaryzacji nie musi wiedzieć nic o kontrolerach widoku ani instancjach innych klas, które mogą być zainteresowane wiedzą, kiedy zmienia się zbiór elementów inwentaryzacji; NSNotificationCenter dba o te szczegóły implementacji. Kontrolery widoku po prostu subskrybują powiadomienia, a Menedżer danych po prostu publikuje powiadomienia.

Wielu początkujących programistów korzysta z faktu, że zawsze jest dokładnie jeden Delegat aplikacji w okresie życia aplikacji, który jest globalnie dostępny. Początkujący Programiści wykorzystują ten fakt do umieszczania obiektów i funkcjonalności w aplikacji, aby ułatwić dostęp z dowolnego miejsca w aplikacji. To, że AppDelegate jest singletonem, nie oznacza, że powinien zastąpić wszystkie inne singletony. Jest to słaba praktyka, ponieważ nakłada zbyt duże obciążenie na jedną klasę, łamiąc dobre praktyki zorientowane obiektowo. Każda klasa powinna mieć wyraźna rola, którą łatwo wyjaśnić, często po prostu przez nazwę klasy.

Za każdym razem, gdy Delegat aplikacji zacznie się nadęty, zacznij usuwać funkcjonalność do singletonów. Na przykład, podstawowy stos danych nie powinien być pozostawiany w AppDelegate, ale powinien być umieszczony w jego własnej klasie, klasie coreDataManager.

Referencje

 48
Author: Jason Cross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 12:56:35

Istnieje wiele metod udostępniania danych.

  1. Zawsze możesz udostępniać dane za pomocą NSUserDefaults. Ustaw wartość, którą chcesz udostępnić w odniesieniu do wybranego klucza i uzyskaj wartość z NSUserDefault powiązaną z tym kluczem w kontrolerze następnego widoku.

    [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]
    [[NSUserDefaults standardUserDefaults] objectForKey:key]
    
  2. Możesz po prostu utworzyć właściwość w viewcontrollerA. Utwórz obiekt viewcontrollerA w viewcontrollerB i przypisz żądaną wartość do tej właściwości.

  3. Możesz także tworzyć własne delegaty dla to.

 37
Author: Anubrata Santra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-24 07:39:34

Przekazywanie danych z ViewController 2(destination) do ViewController 1(Source) jest ciekawszą rzeczą. Zakładając, że używasz storyBoard, to są wszystkie sposoby, które odkryłem:

  • Delegat
  • zgłoszenie
  • User defaults
  • Singleton

Były już omawiane tutaj.

Znalazłem więcej sposobów:

-używanie wywołań blokujących:

Użyj go w metodzie prepareForSegue w VC1

NextViewController *destinationVC = (NextViewController *) segue.destinationViewController;
[destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC)
{
    self.blockLabel.text = destination.blockTextField.text;
}];

-za pomocą storyboards Unwind (Exit)

Zaimplementuj metodę z argumentem UIStoryboardSegue w VC 1, Jak Ta:

-(IBAction)UnWindDone:(UIStoryboardSegue *)segue { }

W storyboardzie hak przycisk" Powrót " do zielonego wyjścia przycisk (Rozwiń) vc. Teraz masz segue, który "wraca", więc możesz użyć destinationViewController property in the preparedforsegue of VC2 and Zmień dowolną właściwość VC1, zanim wróci.

  • Kolejna opcja użycia storyboardów Undwind ( Exit) - możesz użyj metoda, którą napisałeś w VC1

    -(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
        NextViewController *nextViewController = segue.sourceViewController;
        self.unwindLabel.text = nextViewController.unwindPropertyPass;
    } 
    

    I w prepareForSegue VC1 możesz zmienić dowolną właściwość, którą chcesz udostępnić.

W obu opcjach rozwiń można ustawić właściwość tag przycisku i zaznaczyć ją w przygotowanie do egzaminu.

Mam nadzieję, że dodałem coś do dyskusji.

[[4]}:) Pozdrawiam.
 37
Author: Yevgeni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 05:14:55

OP nie wspomniał o kontrolerach widoku, ale tak wiele odpowiedzi Ma, że chciałem się dowiedzieć, co niektóre nowe funkcje LLVM pozwalają to ułatwić, gdy chcą przekazać dane z jednego kontrolera widoku do drugiego, a następnie uzyskać pewne wyniki z powrotem.

Storyboard segues, Arc i LLVM Blocks sprawiają, że jest to łatwiejsze niż kiedykolwiek. Niektóre odpowiedzi wyżej wymienione storyboardy i segmenty już, ale nadal opierał się na delegacji. Definiowanie delegatów na pewno działa, ale niektóre ludziom może być łatwiej przekazać wskaźniki lub bloki kodu.

Dzięki Uinavigatorom i seguesom istnieją łatwe sposoby przekazywania informacji do kontrolera podrzędnego i odzyskiwania informacji. ARC sprawia, że przekazywanie wskaźników do rzeczy pochodzących z NSObjects jest proste, więc jeśli chcesz, aby kontroler podrzędny dodał/zmienił / zmodyfikował niektóre dane, przekaż mu wskaźnik do mutowalnej instancji. Bloki ułatwiają przekazywanie akcji, więc jeśli chcesz, aby kontroler podrzędny wywoływał akcję na twój kontroler wyższego poziomu, podaj blokadę. Definiujesz blok tak, aby akceptował dowolną liczbę argumentów, które mają dla ciebie sens. Możesz również zaprojektować interfejs API tak, aby używał wielu bloków, jeśli to lepiej pasuje.

Oto dwa trywialne przykłady kleju segue ' a. Pierwszy jest prosty pokazując jeden parametr przekazany do wejścia, drugi do wyjścia.
// 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];
}

Ten drugi przykład pokazuje przekazanie bloku wywołania zwrotnego dla drugiego argumentu. Lubię używać klocków, ponieważ utrzymuje istotne szczegóły blisko siebie w źródle-źródle wyższego poziomu.

// 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];
    }];
}
 35
Author: WeakPointer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 22:26:12

Jeśli chcesz przekazać dane z jednego kontrolera do drugiego, wypróbuj ten kod

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];
 }
 26
Author: user2998756,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-24 19:25:57

Szukałem tego rozwiązania przez długi czas, Atlast znalazłem go. Przede wszystkim zadeklaruj wszystkie obiekty w kontrolerze SecondViewController.plik h jak

@interface SecondViewController: UIviewController 
{
    NSMutableArray *myAray;
    CustomObject *object;
}

Teraz w pliku implementacji przydziel pamięć dla takich obiektów

- (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;
}

Teraz przydzielono pamięć dla Array I obiektu. teraz możesz wypełnić tę pamięć przed naciśnięciem tego ViewController

Przejdź do kontrolera SecondViewController.h i napisać dwie metody

-(void)setMyArray:(NSArray *)_myArray;
-(void)setMyObject:(CustomObject *)_myObject;

W pliku implementacji można implementacja funkcji

-(void)setMyArray:(NSArray *)_myArray
{
     [myArra addObjectsFromArray:_myArray];
}
-(void)setMyObject:(CustomObject *)_myObject
{
     [object setCustomObject:_myObject];
}

Spodziewając się, że Twój CustomObject musi mieć z nim funkcję settera.

Teraz twoja podstawowa praca jest skończona. przejdź do miejsca, w którym chcesz nacisnąć SecondViewController i wykonaj następujące czynności

SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]] ;
[secondView setMyArray:ArrayToPass];
[secondView setMyObject:objectToPass];
[self.navigationController pushViewController:secondView animated:YES ];

Uważaj na błędy ortograficzne.

 25
Author: AsifHabib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 09:29:03

To nie jest sposób, aby to zrobić, powinieneś użyć delegatów, zakładam, że mamy dwa kontrolery widoku ViewController1 i ViewController2 i to sprawdzanie jest w pierwszym i kiedy jego stan się zmieni, chcesz zrobić coś w ViewController2, aby to osiągnąć we właściwy sposób, powinieneś zrobić poniżej:

Dodaj nowy plik do swojego projektu (Objective-C Protocol) File - > New, teraz nazwij go ViewController1Delegate lub jak chcesz i zapisz je pomiędzy @ interface I @end dyrektywy

@optional

- (void)checkStateDidChange:(BOOL)checked;

Teraz przejdź do ViewController2.h i dodać

#import "ViewController1Delegate.h"

Następnie zmień jego definicję na

@interface ViewController2: UIViewController<ViewController1Delegate>

Teraz przejdź do ViewController2.m i wewnątrz implementacji dodać:

- (void)checkStateDidChange:(BOOL)checked {
     if (checked) {
           // Do whatever you want here
           NSLog(@"Checked");
     }
     else {
           // Also do whatever you want here
           NSLog(@"Not checked");
     }
}

Teraz przejdź do ViewController1.h i dodać następującą właściwość:

@property (weak, nonatomic) id<ViewController1Delegate> delegate; 

Teraz jeśli tworzysz ViewController1 wewnątrz ViewController2 po jakimś zdarzeniu, powinieneś zrobić to w ten sposób używając plików NIB:

ViewController1* controller = [[NSBundle mainBundle] loadNibNamed:@"ViewController1" owner:self options:nil][0];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];

Teraz masz wszystko ustawione, za każdym razem, gdy wykryjesz Zdarzenie check zmiana w ViewController1, wszystko, co musisz zrobić, to poniższy

[delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control
Proszę, powiedz mi, czy jest coś, co nie jest jasne, czy dobrze nie zrozumiałem twojego pytania.
 21
Author: Boda Taljo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-01 19:46:45

Jeśli chcesz wysyłać dane z jednego do drugiego kontrolera viewcontrollera, oto sposób na to:

Powiedzmy, że mamy viewcontrollery: viewControllerA i viewControllerB

Teraz w viewControllerB.h

@interface viewControllerB : UIViewController {

  NSString *string;
  NSArray *array;

}

- (id)initWithArray:(NSArray)a andString:(NSString)s;

W 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;

}

W 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];

}

Tak więc możesz przekazać dane z viewControllerA do viewcontrollerb bez ustawiania delegata. ;)

 18
Author: Aniruddh Joshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-29 10:28:43

1. tworzy instancję kontrolera pierwszego widoku w kontrolerze drugiego widoku i tworzy jego właściwość @property (nonatomic,assign).

2. Przypisz instancję SecondviewController tego kontrolera widoku.

2. po zakończeniu operacji zaznaczenia skopiuj tablicę do kontrolera pierwszego widoku, gdy u rozładujesz SecondView, FirstView będzie przechowywać dane tablicy.

Mam Nadzieję, Że To Pomoże.
 18
Author: kaar3k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-18 04:54:17

Przekazywanie danych pomiędzy Firstviewcontrollerem do SecondViewController jak poniżej

Na przykład:

FirstViewController string value as

StrFirstValue = @"first";

Więc możemy przekazać tę wartość w drugiej klasie używając poniższego kroku

1>musimy utworzyć obiekt string w SecondViewController.plik h

NSString *strValue;

2>trzeba zadeklarować własność, jak poniżej poniżej deklaracja w .plik h

@property (strong, nonatomic)  NSString *strSecondValue;

3 > trzeba zsyntetyzować tę wartość w FirstViewController.m plik poniżej nagłówka deklaracja

@synthesize strValue;

Oraz w FirstViewController.h:

@property (strong, nonatomic)  NSString *strValue;

4 > w FirstViewController, z której metody przechodzimy do drugiego widoku, prosimy o wpisanie poniższego kodu w tej metodzie.

SecondViewController *secondView= [[SecondViewController alloc]     
initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]];

[secondView setStrSecondValue:StrFirstValue];

[self.navigationController pushViewController:secondView animated:YES ];
 16
Author: Chris Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-07 20:05:06

Obecnie przyczyniam się do rozwiązania tego problemu poprzez projekt o nazwie MCViewFactory, który można znaleźć tutaj:

Https://github.com/YetiHQ/manticore-iosviewfactory

[3]}pomysł naśladuje paradygmat intencji Androida, używając globalnej fabryki do zarządzania widokiem, na który patrzysz, i używając "intencji" do przełączania i przekazywania danych między widokami. Cała dokumentacja znajduje się na stronie github, ale oto kilka najważniejszych rzeczy:

You setup all twoje poglądy w .Pliki XIB i zarejestrować je w delegat aplikacji, podczas inicjalizacji fabryki.

// Register activities

MCViewFactory *factory = [MCViewFactory sharedFactory];

// the following two lines are optional. 
[factory registerView:@"YourSectionViewController"]; 

Teraz, w Twoim VC, za każdym razem, gdy chcesz przejść do nowego VC i przekazać dane, tworzysz nowy intent i dodajesz dane do jego słownika (savedInstanceState). Następnie po prostu Ustaw bieżący zamiar fabryki:

MCIntent* intent = [MCIntent intentWithSectionName:@"YourSectionViewController"];
[intent setAnimationStyle:UIViewAnimationOptionTransitionFlipFromLeft];
[[intent savedInstanceState] setObject:@"someValue" forKey:@"yourKey"];
[[intent savedInstanceState] setObject:@"anotherValue" forKey:@"anotherKey"];
// ...
[[MCViewModel sharedModel] setCurrentSection:intent];

Wszystkie Twoje widoki, które są zgodne z tym muszą być podklasami MCViewController, które pozwalają na nadpisanie nowej metody onResume:, umożliwiając dostęp do danych, które masz zdałem.

-(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];
}

Mam nadzieję, że niektórzy z was uznają to rozwiązanie za przydatne/interesujące.

 16
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-16 17:18:29

W moim przypadku użyłem klasy singleton, która może działać jako globalny obiekt pozwalający na dostęp do danych z niemal każdego miejsca w aplikacji. Pierwszą rzeczą jest zbudowanie klasy singleton. Proszę zapoznać się ze stroną" Jak powinien wyglądać mój Objective-C singleton? " Aby obiekt był globalnie dostępny, po prostu zaimportowałem go do appName_Prefix.pch , co służy do stosowania instrukcji import w każdej klasie. Aby uzyskać dostęp do tego obiektu i użyć, po prostu zaimplementowałem metodę klasy, aby zwrócić współdzielona instancja, która zawiera własne zmienne

 14
Author: petershine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Utwórz właściwość na next view controller .h i zdefiniuj getter i setter.

Dodaj to property w NextVC.h on nextVC

@property (strong, nonatomic) NSString *indexNumber;

Dodaj

@synthesize indexNumber; w NextVC.m

I ostatni

NextVC *vc=[[NextVC alloc]init];

vc.indexNumber=@"123";

[self.navigationController vc animated:YES];
 13
Author: Vivek Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-23 06:50:54

Wiem, że jest to pobity temat, ale dla tych, którzy chcą odpowiedzieć na to pytanie z szybkim pochyleniem i chcą przykładu gołych kości, oto moja metoda przekazywania danych, jeśli używasz segue, aby ominąć.

Jest podobny do powyższego, ale bez przycisków, etykiet i tym podobnych. Wystarczy po prostu przekazać dane z jednego widoku do drugiego.

Setup The Storyboard

Istnieją trzy części.

  1. Nadawca
  2. Segue
  3. The Odbiornik

Jest to bardzo prosty układ widoku z segue między nimi.


Bardzo prosty układ widoku.  Uwaga: brak kontrolera nawigacji


Oto konfiguracja dla nadawcy


Nadawca


Oto konfiguracja odbiornika.


Odbiornik


Wreszcie, konfiguracja dla segue.


Identyfikator Segue ' A


Kontrolery Widoku

Utrzymujemy to proste, więc żadnych przycisków, nie akcje, po prostu przenosimy dane z nadawcy do odbiorcy podczas ładowania aplikacji, a następnie wysyłamy przesyłaną wartość do konsoli.

Ta strona pobiera wstępnie załadowaną wartość i przekazuje ją dalej.

//
//  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

    }

}

Ta strona po prostu wysyła wartość zmiennej do konsoli podczas ładowania. W tym momencie nasz ulubiony film powinien być w tej zmiennej.

//
//  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)")

    }



}

Tak możesz sobie z tym poradzić, jeśli chcesz użyć segue i nie masz swoich stron pod kontroler nawigacji.

Po uruchomieniu powinien automatycznie przełączyć się do widoku odbiornika i przekazać wartość od nadawcy do odbiorcy, wyświetlając wartość w konsoli.

Pogromcy duchów to klasyka.

 12
Author: Christopher Wade Cantley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 15:28:28

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;
 10
Author: Mohsin Sabasara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-24 12:27:05

Delegacja jest jedynym rozwiązaniem do wykonywania takich operacji podczas korzystania .pliki xib jednak wszystkie odpowiedzi opisane powyżej są dla storyboard dla .pliki xibs, których potrzebujesz, aby użyć delegacji. to jedyne rozwiązanie, jakie możesz.

Innym rozwiązaniem jest użycie wzorca klasy singleton zainicjuj go raz i użyj go w całej aplikacji.

 10
Author: user2786888,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-07 19:43:04

Jeśli chcesz przekazać dane z Viewcontrollerone do viewcontrollertwo, spróbuj tego..

Zrób to w Viewcontrollerone.h

 @property (nonatomic, strong) NSString *str1;

Zrób to w ViewController Two.h

 @property (nonatomic, strong) NSString *str2;

Zsyntetyzuj str2 w ViewControllerTwo.m

@interface ViewControllerTwo ()
@end
@implementation ViewControllerTwo
@synthesize str2;

Zrób to w Viewcontrollerone.m

 - (void)viewDidLoad
 {
   [super viewDidLoad];

  // Data or string you wants to pass in ViewControllerTwo..
  self.str1 = @"hello world";

 }

Na przyciskach kliknij Zdarzenie zrób to..

-(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];
}

Zrób to w ViewController Two.m

- (void)viewDidLoad
{
 [super viewDidLoad];
  NSLog(@"%@",str2);
}
 10
Author: krushnsinh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-27 14:16:58

Możesz zapisać dane w App delegate, aby uzyskać do nich dostęp między kontrolerami widoku w aplikacji. Wszystko, co musisz zrobić, to utworzyć współdzieloną instancję app delegate

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

Na Przykład

Jeśli zadeklarujesz NSArray object *arrayXYZ, możesz uzyskać do niego dostęp w dowolnym kontrolerze widoku przez appDelegate.arrayXYZ

 10
Author: ak_tyagi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-25 20:09:25

Istnieje mnóstwo sposobów, aby to zrobić i ważne jest, aby wybrać właściwy. Prawdopodobnie jedną z największych decyzji architektonicznych jest to, w jaki sposób kod modelu będzie udostępniany lub dostępny w całej aplikacji.

Jakiś czas temu napisałem o tym wpis na blogu: dzielenie się kodem modelu . Oto krótkie podsumowanie:

Wspólne dane

Jedną z metod jest współdzielenie wskaźników do obiektów modelu pomiędzy kontrolerami widoku.

  • iteracja Brute force na kontrolerach widoku (w kontrolerze nawigacji lub paska kart), aby ustawić dane
  • W tym celu należy wykonać następujące czynności:]}

Ponieważ przygotowanie do segue ' a jest najczęstszym oto przykład:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var next = segue.destinationViewController as NextViewController
    next.dataSource = dataSource
}

Niezależny dostęp

Innym podejściem jest obsługa ekranu pełnego danych na raz i zamiast łączenia kontrolerów widoku ze sobą para kontrolerów widoku do jednego źródła danych, do którego mogą dostać się niezależnie.

Najbardziej powszechnym sposobem, w jaki to robiłem, jest instancjasingleton . Jeśli więc twoim pojedynczym obiektem był DataAccess, możesz wykonać następujące czynności w metodzie viewDidLoad w UIViewController:

func viewDidLoad() {
    super.viewDidLoad()
    var data = dataAccess.requestData()
}

Istnieją dodatkowe narzędzia, które również pomagają przekazywać dane:

  • Obserwacja Wartości Klucza
  • NSNotification
  • Podstawowe Dane
  • NSFetchedResultsController
  • Źródło Danych

Podstawowe Dane

Fajną rzeczą w Core Data jest to, że ma odwrotne relacje. Więc jeśli chcesz po prostu dać NotesViewController obiekt notes, który możesz, ponieważ będzie miał odwrotną relację do czegoś innego, takiego jak Notatnik. Jeśli potrzebujesz danych z notatnika w kontrolerze NotesViewController, możesz wykonać kopię zapasową wykresu obiektu wykonując następujące czynności:

let notebookName = note.notebook.name

Czytaj więcej na ten temat w moim wpisie na blogu: dzielenie się kodem modelu

 10
Author: Korey Hinton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 12:46:56

Jeśli chcesz wysyłać dane z jednego do drugiego kontrolera viewController, oto sposób na to:

Powiedzmy, że mamy viewcontrollery: ViewController i NewViewController.

W 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

W 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];

}

W NewViewController.h

#import <UIKit/UIKit.h>

@interface NewViewController : UITableViewController
{
    NSArray *arrayList;

    NSString *name,*age,*dob,*mobile;

}

@property(nonatomic, retain)NSArray *arrayList;

@end

W 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

W ten sposób możemy przekazać dane z jednego kontrolera widoku do innego kontrolera widoku...

 8
Author: Sabs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-05 05:06:49

Podoba mi się idea obiektów modelowych i Mockowych opartych na NSProxy do zatwierdzania lub odrzucania danych, jeśli to, co wybierze użytkownik, może zostać anulowane.

Łatwo jest przekazywać dane, ponieważ jest to pojedynczy obiekt lub kilka obiektów, a jeśli masz na przykład kontroler UINavigationController, możesz zachować odniesienie do modelu w środku, a wszystkie kontrolery widoku pchanego mogą uzyskać do niego dostęp bezpośrednio z kontrolera nawigacji.

 8
Author: highmaintenance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 16:09:38

Widziałem wiele osób, które komplikują to za pomocą metody didSelectRowAtPath. W moim przykładzie wykorzystuję Podstawowe Dane.

- (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 linie kodu wewnątrz metody i gotowe.

 7
Author: App Dev Guy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-16 03:18:43

To jest naprawdę świetny tutorial dla każdego, kto chce. Oto przykładowy kod:

- (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];
    }
}
 3
Author: crazy_tiger_corp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-28 09:43:35

Istnieje wiele odpowiedzi na te pytania, oferujących wiele różnych sposobów komunikacji z kontrolerem widoku, które rzeczywiście by działały, ale nie widzę nigdzie wzmianki, które z nich są najlepsze do użycia, a których unikać.

W praktyce moim zdaniem zaleca się tylko kilka rozwiązań:

  • aby przekazać dane do przodu:
    • override prepare(for:sender:) metoda UIViewController przy użyciu storyboard i segues
    • przekazywanie danych przez inicjalizator lub przez właściwości podczas wykonywania przejść kontrolera widoku thtough code
  • aby przekazać dane do tyłu
    • zaktualizuj stan współdzielony aplikacji (który możesz przekazać do przodu między kontrolerami widoku za pomocą jednej z powyższych metod)
    • użyj delegacji
    • użyj rozwinięcia segue

Rozwiązania, których nie polecam używać:

  • odwoływanie się bezpośrednio do poprzedniego kontrolera zamiast do delegowania
  • dzielenie danych przez singleton
  • Przekazywanie danych przez delegata aplikacji
  • udostępnianie danych poprzez domyślne ustawienia użytkownika
  • Przekazywanie danych przez powiadomienia

Te rozwiązania, chociaż działają w krótkim czasie, wprowadzają zbyt wiele zależności, które będą garbować architekturę aplikacji i tworzyć więcej problemów później.

Dla zainteresowanych napisałem kilka artykułów, które odnoszą się do tych punktów bardziej dogłębnie i podkreślają różne wady:

 3
Author: Matteo Manferdini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-03 15:27:48