Передать переменные с одного контроллера на другой в Swift [duplicate]

Это не работает, но я работал над простым сервером PhantomJS для Heorku , который будет анализировать любой клиентский JS. Я использую его специально для Angular и Rails для подачи HTML-запросов на бот.

1206
задан Tamás Sengel 17 April 2018 в 01:51
поделиться

30 ответов

Этот вопрос, кажется, очень популярен здесь в stackoverflow, поэтому я решил попробовать и дать лучший ответ, чтобы помочь людям, начинающим в мире iOS, как я.

Надеюсь, что этот ответ ясен

Передача данных вперед

Передача данных в контроллер просмотра с другого контроллера. Вы должны использовать этот метод, если хотите передать объект / значение с одного контроллера вида на другой контроллер представления, который вы можете нажать в стек навигации.

В этом примере мы будем иметь ViewControllerA и ViewControllerB

Чтобы передать значение BOOL с ViewControllerA на ViewControllerB, мы сделали бы следующее.

  1. в ViewControllerB.h создать свойство для BOOL
    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA вам нужно рассказать об этом ViewControllerB, поэтому используйте
    #import "ViewControllerB.h"
    
    Затем, где вы хотите загрузить представление, например. didSelectRowAtIndex или несколько IBAction вам нужно установить свойство в ViewControllerB, прежде чем вы нажмете его на стек навигатора.
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];
    
    Это установит isSomethingEnabled в значение ViewControllerB на BOOL значение YES.

Передача данных вперед с помощью Segues

Если вы используете раскадровки вы, скорее всего, используете segues и будете нуждаться в этой процедуре для передачи данных вперед. Это похоже на приведенное выше, но вместо передачи данных перед тем, как вы нажимаете контроллер вида, вы используете метод, называемый

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

. Итак, чтобы передать BOOL с ViewControllerA на ViewControllerB, мы выполнил бы следующее:

  1. в ViewControllerB.h создать свойство для BOOL
    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA, вам нужно рассказать об этом ViewControllerB поэтому используйте
    #import "ViewControllerB.h"
    
  3. Создайте выделение от ViewControllerA до ViewControllerB на раскадровке и дайте ему идентификатор, в этом примере мы будем называть его "showDetailSegue"
  4. Затем нам нужно добавить метод к ViewControllerA, который вызывается, когда выполняется какой-либо segue, из-за этого нам нужно определить, какой вызов был вызван, а затем что-то сделать. В нашем примере мы проверим "showDetailSegue", и если это будет выполнено, мы передадим наше значение BOOL в ViewControllerB
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.identifier isEqualToString:@"showDetailSegue"]){
            ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
            controller.isSomethingEnabled = YES;
        }
    }
    
    . Если у вас есть свои представления, встроенные в контроллер навигации, вам нужно немного изменить метод выше на следующие
    -(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;
        }
    }
    
    Это установит isSomethingEnabled в ViewControllerB на значение BOOL YES.

Передача данных Назад

Чтобы передать данные с ViewControllerB ] до ViewControllerA вам нужно использовать Protocols and Delegates или Blocks , последний может использоваться как слабо связанный механизм для обратных вызовов.

To сделаем это, мы сделаем ViewControllerA делегатом из ViewControllerB. Это позволяет ViewControllerB отправить сообщение обратно на ViewControllerA, чтобы мы могли отправить данные назад.

Чтобы ViewControllerA был делегатом ViewControllerB, он должен соответствовать протоколу ViewControllerB, который мы должны указать. Это указывает ViewControllerA, какие методы он должен реализовать.

  1. В ViewControllerB.h ниже #import, но выше @interface вы указываете протокол.
    @class ViewControllerB;
    
    @protocol ViewControllerBDelegate <NSObject>
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
    @end
    
  2. далее в ViewControllerB.h вам нужно настроить свойство delegate и синтезировать в ViewControllerB.m
    @property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
    
  3. В ViewControllerB мы вызываем сообщение на delegate, когда мы выходим на контроллер вида.
    NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
    
  4. Это для ViewControllerB. Теперь в ViewControllerA.h скажите ViewControllerA, чтобы импортировать ViewControllerB и соответствовать его протоколу.
    #import "ViewControllerB.h"
    
    @interface ViewControllerA : UIViewController <ViewControllerBDelegate>
    
  5. В ViewControllerA.m реализуем следующий метод из нашего протокола
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
    {
        NSLog(@"This was returned from ViewControllerB %@",item);
    }
    
  6. . Перед нажатием viewControllerB в стек навигации нам нужно сообщить ViewControllerB, что ViewControllerA является его делегатом, иначе мы получим сообщение об ошибке.
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.delegate = self
    [[self navigationController] pushViewController:viewControllerB animated:YES];
    

Ссылки

1558
ответ дан Graham 15 August 2018 в 18:20
поделиться
  • 1
    Должны ли мы также поставить @class ViewControllerB; над определением @protocol? Без этого я получаю «Ожидаемый тип». ошибка в ViewControllerB в строке: - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item; в объявлении @protocol – alan-p 30 August 2012 в 14:16
  • 2
    Это отлично работает. Как говорит alan-p, не забудьте написать @class ViewControllerB; выше протокола, иначе вы получите «Ожидаемый тип», ошибка. – Andrew Davis 22 November 2012 в 13:11
  • 3
    вам не нужны делегаты для передачи назад, просто используйте разматывать. – malhal 27 September 2013 в 04:30
  • 4
    Когда я помещаю & quot; viewControllerB.delegate = self; & quot; в ViewControllerB Я получаю сообщение об ошибке. Назначение 'id & lt; ViewControllerBDelegate & gt;' из несовместимого типа 'ViewControllerB * const __strong', я не уверен, что я делаю неправильно. Может ли кто-нибудь помочь? Плюс мне пришлось изменить: initWithNib - & gt; initWithNibName. – uplearnedu.com 28 March 2014 в 23:21
  • 5
    если вы используете NavigationController, вы должны использовать [self.navigationController pushViewController:viewController animated:YES]; вместо [self pushViewController:viewControllerB animated:YES]; – Nazir 5 June 2014 в 06:26

Существуют различные способы, с помощью которых данные могут быть получены в другом классе в iOS. Например,

  1. Прямая инициализация после выделения другого класса.
  2. Делегирование - для передачи данных назад
  3. Уведомление - для трансляции данных в несколько классов за один раз
  4. Сохранение в NSUserDefaults - для доступа к нему позже
  5. Одиночные классы
  6. Базы данных и другие механизмы хранения, такие как plist и т. д.

Но для простого сценария передачи значения другому классу, распределение которого выполняется в текущем классе, наиболее распространенным и предпочтительным методом будет прямая настройка значений после выделения. Это делается следующим образом: -

Мы можем понять это с помощью двух контроллеров - Controller1 и Controller2

Предположим, что в классе Controller1 вы хотите создать объект Controller2 и нажать его со значением String передается. Это можно сделать следующим образом: -

- (void)pushToController2 {

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

В реализации класса Controller2 будет существовать эта функция as-

@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

. Вы также можете прямо установить свойства класс Controller2 аналогичным образом:

- (void)pushToController2 {

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

Чтобы передать несколько значений, вы можете использовать несколько параметров, таких как: -

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

Или если вам нужно пройти больше чем 3 параметра, которые связаны с общей функцией, вы можете сохранить значения в классе Model и передать этот объект modelObject следующему классу

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

Итак, если вы хотите -

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.

Надеюсь, это поможет

85
ответ дан Aaron Brager 15 August 2018 в 18:20
поделиться

Передача данных из ViewController 2 (destination) в viewController 1 (Source) является более интересной. Предполагая, что вы используете storyBoard, это все, что я узнал:

  • Delegate
  • Уведомление
  • Пользовательские настройки по умолчанию
  • Singleton

Те были обсуждены здесь уже.

Я обнаружил, что существует больше способов:

-Использование обратных вызовов блоков:

use это в методе prepareForSegue в VC1

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

-Использование раскадровки Unwind (Exit)

Внедрить метод с аргументом UIStoryboardSegue в VC 1, как этот:

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

В окне storyBoard нажмите кнопку «вернуться» к зеленой кнопке «Выход» («Разморозь») vc. Теперь у вас есть segue, который «возвращается», поэтому вы можете использовать свойство destinationViewController в файле readyForSegue of VC2 и изменить любое свойство VC1 до его возврата.

  • Другой вариант использования раскадровки Undwind ( Exit) - вы можете использовать метод, который вы написали в VC1
    -(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
        NextViewController *nextViewController = segue.sourceViewController;
        self.unwindLabel.text = nextViewController.unwindPropertyPass;
    } 
    
    . И в prepareForSegue of VC1 вы можете изменить любое свойство, которое хотите разделить.

В обоих вариантах размотки вы можете установить тег свойства кнопки и проверить его в prepareForSegue.

Надеюсь, я добавил что-то к обсуждению.

:) Приветствия.

37
ответ дан Alexander Abakumov 15 August 2018 в 18:20
поделиться

Если вы хотите отправлять данные от одного к другому viewController, вот путь к нему:

Скажем, у нас есть viewControllers: viewControllerA и viewControllerB

Теперь в viewControllerB.h

@interface viewControllerB : UIViewController {

  NSString *string;
  NSArray *array;

}

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

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

}

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

}

Так вы можете передавать данные с viewControllerA в viewControllerB без установки любого делегата. ;)

18
ответ дан Aniruddh Joshi 15 August 2018 в 18:20
поделиться
  • 1
    Я попытался использовать ваш код в своем проекте, но не могу получить значения в контроллере вида. Можете ли вы рассказать мне, что может быть проблемой? – The X-Coder 28 January 2013 в 11:07
  • 2
    @Ajitthala Можете ли вы вставить свой код в новый вопрос? Я постараюсь решить вашу проблему. :) – Aniruddh Joshi 28 January 2013 в 14:00
  • 3
    неправильно ли использовать методы init и просто делать что-то вроде vcB.string = @ & quot; asdf & quot; из viewcontroller A? – khanh.tran.vinh 3 September 2013 в 06:55
  • 4
    @ khanh.tran.vinh Зависит от того, используете ли вы ARC или нет. – Aniruddh Joshi 22 September 2013 в 10:11

Я видел много людей, которые усложняли это, используя метод didSelectRowAtPath. Я использую 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 строки кода внутри метода, и все готово.

7
ответ дан App Dev Guy 15 August 2018 в 18:20
поделиться

Существует несколько способов совместного использования данных.

  1. Вы всегда можете обмениваться данными с помощью NSUserDefaults. Задайте значение, которое вы хотите использовать, по отношению к выбранному вами ключу, и получите значение из NSUserDefault, связанное с этим ключом в следующем контроллере представления.
    [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]
    [[NSUserDefaults standardUserDefaults] objectForKey:key]
    
  2. Вы можете просто создать свойство в viewcontrollerA. Создайте объект viewcontrollerA в viewcontrollerB и назначьте это значение этому свойству.
  3. Вы также можете создавать пользовательские делегаты для этого.
37
ответ дан Bhavin Ramani 15 August 2018 в 18:20
поделиться
  • 1
    Типичной целью NSUserDefaults является сохранение пользовательских настроек, которые сохраняются между выполнением приложений, поэтому все, что хранится здесь, останется здесь, если явно не удалено. Это очень плохая идея использовать это для передачи информации между контроллерами представлений (или любыми другими объектами) в приложении. – José González 17 May 2014 в 08:00

Это не способ сделать это, вы должны использовать делегатов, я предполагаю, что у нас есть два контроллера вида ViewController1 и ViewController2, и эта вещь проверки находится в первой и когда ее состояние изменяется, вы хотите сделать что-то в ViewController2, чтобы добиться этого правильно, вы должны сделать следующее:

Добавить новый файл в ваш проект (Objective-C Protocol) File -> New, теперь назовите его ViewController1Delegate или что хотите и напишите их между директивами @interface и @end

@optional

- (void)checkStateDidChange:(BOOL)checked;

Теперь перейдите в ViewController2.h и добавьте

#import "ViewController1Delegate.h"

, затем измените его определение на

@interface ViewController2: UIViewController<ViewController1Delegate>

Теперь перейдите в ViewController2.m и внутри реализации add:

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

Теперь перейдите в ViewController1.h и добавьте следующее свойство:

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

Теперь, если вы создают ViewController1 внутри ViewController2 после некоторого события, тогда вы должны сделать это так, используя файлы NIB:

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

Теперь вы все настроены, всякий раз, когда вы обнаруживаете, что событие проверки изменилось в ViewController1, все, что вы нужно сделать ниже

[delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control

Пожалуйста, скажите мне, есть ли что-то, что не ясно, если я не понял ваш вопрос правильно.

21
ответ дан Boda Taljo 15 August 2018 в 18:20
поделиться

M в MVC для «Модели», а в парадигме MVC роль классов моделей заключается в управлении данными программы. Модель противоположна представлению - представление знает, как отображать данные, но ничего не знает о том, что делать с данными, тогда как модель знает все о том, как работать с данными, но ничего о том, как ее отображать. Модели могут быть сложными, но они не обязательно должны быть - модель для вашего приложения может быть такой же простой, как массив строк или словарей.

Роль контроллера заключается в посредничестве между представлением и модель. Поэтому им нужна ссылка на один или несколько объектов вида и один или несколько объектов модели. Предположим, что ваша модель представляет собой массив словарей, причем каждый словарь представляет одну строку в вашей таблице. Корневой вид для вашего приложения отображает эту таблицу, и он может отвечать за загрузку массива из файла. Когда пользователь решает добавить новую строку в таблицу, они нажимают какую-то кнопку, и ваш контроллер создает новый (изменяемый) словарь и добавляет его в массив. Чтобы заполнить строку, контроллер создает контроллер подробного представления и дает ему новый словарь. Контроллер подробного представления заполняет словарь и возвращает его. Словарь уже является частью модели, поэтому ничего не должно произойти.

118
ответ дан Caleb 15 August 2018 в 18:20
поделиться

Я знаю, что это избитый предмет, но для тех, кто хочет ответить на этот вопрос с наклоном SWIFT и хочет пример с голубыми костями, вот мой метод go-to для передачи данных, если вы используете segue, чтобы обойти.

Это похоже на вышесказанное, но без кнопок, меток и т. д. Просто передавайте данные с одного вида на другой.

Настройка Раскадровка

Есть три части.

  1. Отправитель
  2. Segue
  3. Приемник

Это очень простой макет представления с segue между ними.



Вот настройка для отправителя



Вот настройка приемника.



Наконец, настройка для сеанса.



Контроллеры просмотра

Мы придерживаемся этого простого поэтому никаких кнопок, а не действий, мы просто перемещаем данные от отправителя к получателю, когда приложение загружается, а затем выводит переданное значение на консоль.

Эта страница берет первоначально загруженное значение и передает его .

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

    }

}

Эта страница просто отправляет значение переменной на консоль при ее загрузке. К этому моменту наш любимый фильм должен быть в этой переменной.

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

    }



}

Вот как вы можете справиться с этим, если хотите использовать segue, и у вас нет страниц под навигационным контроллером.

После запуска он должен автоматически переключиться на вид приемника и передать значение от отправителя в приемник, отображая значение в консоли.

12
ответ дан Christopher Wade Cantley 15 August 2018 в 18:20
поделиться

В моем случае я использовал одноэлементный класс, который может работать как глобальный объект, позволяющий получать доступ к данным почти везде в приложении. Прежде всего, нужно построить одноэлементный класс. Пожалуйста, обратитесь к странице, «. Как выглядит мой сингл Objective-C? « И то, что я сделал, чтобы сделать объект глобально доступным, просто импортировал его в appName_Prefix.pch, который предназначен для применения оператора импорта в все классы. Чтобы получить доступ к этому объекту и использовать его, я просто применил метод класса для возврата общего экземпляра, который содержит свои собственные переменные

14
ответ дан Community 15 August 2018 в 18:20
поделиться
  • 1
    Это правильный ответ. Просто используйте синглтон как «модель». Обратите внимание, что, как говорит Калеб, "модель для вашего приложения может быть такой же простой, как массив строк & quot; . Очень важно отметить, что делает одноэлемент в Swift, действительно тривиальным . (Так просто даже не стоит упоминать здесь - просто google.) Для новых программистов стоит понять, что делает синглтон когда-то реальной болью в заднице . Тем не менее, синглтоны абсолютно важны для программирования iOS - все, что делает Apple, - это одноэлемент. Вот почему Apple, наконец, сделала это trtvial (в Swift), чтобы правильно сделать синглтоны. – Fattie 29 May 2016 в 15:28
  • 2
    Обратите внимание, однако, что в эти дни (2016+) «все является видом контейнера в iOS». Каждая вещь, которую вы делаете на экране, вы делаете небольшим видом контейнера. Это довольно тривиально, чтобы получить ссылки & quot; вверх и вниз & quot; цепи контейнеров (хотя Apple сделает это проще в будущем), и вы делаете это практически для каждого вида контейнера. Итак, если вы это сделали, у вас есть ответ; нет необходимости в синглетоне. Container view intro ... stackoverflow.com/a/23403979/294884 – Fattie 29 May 2016 в 16:02

Это действительно замечательный учебник для тех, кто его хочет. Вот пример кода:

- (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
ответ дан crazy_tiger_corp 15 August 2018 в 18:20
поделиться

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
ответ дан Florent 15 August 2018 в 18:20
поделиться

Мне нравится идея объектов модели и Mock-объектов на основе NSProxy для фиксации или удаления данных, если пользовательский выбор может быть отменен.

Легко передавать данные, поскольку это один объект или пара объектов, и если вы скажете UINavigationController-контроллер, вы можете сохранить ссылку на модель внутри, и все нажатые контроллеры представлений могут получить к ней доступ непосредственно от контроллера навигации .

8
ответ дан highmaintenance 15 August 2018 в 18:20
поделиться

Делегирование - единственное решение для выполнения таких операций, когда вы используете .xib-файлы, однако все описанные выше ответы предназначены для storyboard для .xibs-файлов, которые необходимо использовать для делегирования. это единственное решение, которое вы можете.

Другим решением является использование singleton class pattern, инициализирующее его один раз и использование его во всем приложении.

18
ответ дан Irfan 15 August 2018 в 18:20
поделиться
  • 1
    Я не верю, что это правильный путь, поскольку он создает очень ограниченную связь между контроллерами представлений. На самом деле не прилипает к MVC. – Matt Price 28 May 2012 в 15:49
  • 2
    Если вы хотите строго следовать MVC, используйте NSNotificationCenter , метод может быть вызван из ViewControllerA в ViewControllerB, проверьте этот , он может помочь u – kaar3k 4 June 2012 в 15:07

После дальнейших исследований казалось, что протоколы и делегаты являются правильными / предпочтительными для Apple способами.

В итоге я использовал этот пример

Обмен данными между представлениями контроллеры и другие объекты @ iPhone Dev SDK

Работал отлично и разрешил мне передавать строку и массив вперед и назад между моими представлениями.

Спасибо за вашу помощь

74
ответ дан Jason Whitehorn 15 August 2018 в 18:20
поделиться
  • 1
    не используйте протоколы и делегаты, просто используйте разматывать. – malhal 27 September 2013 в 04:31
  • 2
    @malhal Что делать, если вы не используете раскадровки? – Evan R 8 November 2015 в 03:30
  • 3
    Я ненавижу бесполезные протоколы и делегаты. @malhal – Dawn Song 9 December 2015 в 07:07
  • 4
    @EvanR Вы можете создавать и выполнять segues в коде. Все то же самое. – Dawn Song 12 December 2015 в 12:27
  • 5
    По существу, весь QA на этой странице «от старых дней до представлений контейнера». Вы никогда в миллион лет не беспокоитесь о протоколах или делегатах. Каждая мелочь, которую вы делаете на любом экране, является контейнером в любом случае, поэтому вопрос действительно не существует - у вас уже есть все ссылки & quot; вверх и вниз & quot; из всех видов контейнеров. – Fattie 29 May 2016 в 16:04

, если вы хотите передать данные из ViewControlerOne в ViewControllerTwo попробовать эти ..

сделать это в ViewControlerOne.h

 @property (nonatomic, strong) NSString *str1;

сделать это в ViewControllerTwo.h

 @property (nonatomic, strong) NSString *str2;

Синтезировать str2 в ViewControllerTwo.m

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

сделать это в ViewControlerOne.m

 - (void)viewDidLoad
 {
   [super viewDidLoad];

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

 }

на кнопке click event сделать это ..

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

делают это в ViewControllerTwo.m

- (void)viewDidLoad
{
 [super viewDidLoad];
  NSLog(@"%@",str2);
}
10
ответ дан krushnsinh 15 August 2018 в 18:20
поделиться

Я нахожу простейшую и самую элегантную версию с прохождением блоков. Давайте назовите контроллер вида, который ожидает возвращенных данных как «A» и возвращает контроллер представления как «B». В этом примере мы хотим получить 2 значения: первый из Type1 и второй из Type2.

Предполагая, что мы используем Storyboard, первый контроллер устанавливает блок обратного вызова, например, во время подготовки segue:

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

    }
}

и «B» должны объявить свойство обратного вызова, BViewController.h:

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

Чем в файле реализации BViewController.m после того, как мы получим желаемые значения для возврата нашего обратного вызова, следует вызвать:

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

Следует помнить, что использование блока часто требует управления сильными и __вековыми ссылками, например здесь

59
ответ дан Leszek Zarna 15 August 2018 в 18:20
поделиться
  • 1
    Почему значение value не является параметром для блока обратного вызова, а не является отдельным свойством? – Timuçin 4 December 2013 в 11:17
  • 2
    это лучшее решение. Если модель одна к одному. Если вам нужно обновить несколько контролов просмотра, выполните следующие действия: Уведомление или делегаты. – Ankish Jain 11 August 2015 в 10:37

Есть много ответов на эти вопросы, предлагающие множество различных способов взаимодействия с диспетчером диспетчера сообщений, которые действительно будут работать, но я не вижу нигде не упомянутых, какие из них лучше всего использовать и какие из них следует избегать.

На практике, на мой взгляд, рекомендуется только несколько решений:

  • Для передачи данных вперед: переопределить метод prepare(for:sender:) в UIViewController при использовании раскадровки и segues передавать данные через инициализатор или через свойства при выполнении переходов контроллера просмотра, т. е. код
  • Чтобы передать данные назад, обновите общее состояние приложения (которое вы можете пройти вперед между контроллерами представлений одним из вышеприведенных методов), используйте делегирование, используя команду unind segue

Решения Я рекомендую НЕ использовать:

  • Ссылка на предыдущий контроллер непосредственно вместо использования делегирования
  • Совместное использование данных через одноэлементный
  • Передача данных через делегат приложения
  • Обмен данными через пользовательские настройки по умолчанию [/ g1 5]
  • Передача данных через уведомления

Эти решения, хотя и работают в краткосрочной перспективе, вводят слишком много зависимостей, которые будут искажать архитектуру приложения и создавать больше проблем позже.

Для тех, кого это интересует, я написал несколько статей, которые более подробно затрагивают эти моменты и выделяют различные недостатки:

3
ответ дан Matteo Manferdini 15 August 2018 в 18:20
поделиться

Я долго искал это решение, Atlast нашел его. Прежде всего объявите все объекты в файле SecondViewController.h, например

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

Теперь в вашем файле реализации выделите память для этих объектов, таких как

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

Теперь у вас есть выделил память для Array и объекта. теперь вы можете заполнить эту память, прежде чем нажимать ViewController

. Перейдите к вашему SecondViewController.h и напишите два метода

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

в файле реализации, вы можете реализовать функцию

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

, ожидая, что ваш CustomObject должен иметь с ним функцию setter.

теперь выполняется ваша основная работа. перейдите к месту, где вы хотите нажать SecondViewController и выполните следующие действия

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

Позаботьтесь о орфографических ошибках.

25
ответ дан Mykola 15 August 2018 в 18:20
поделиться

Если вы хотите передавать данные с одного контроллера на другой, попробуйте этот код

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
ответ дан RckLN 15 August 2018 в 18:20
поделиться
  • 1
    то как мне получить значение str в secondviewcontroller объясните пожалуйста или код .. – vaibhav 18 May 2016 в 08:06

Если вы хотите отправлять данные от одного к другому viewController, вот путь к нему:

Скажем, у нас есть viewControllers: ViewController и NewViewController.

в 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

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

}

В NewViewController.h

#import <UIKit/UIKit.h>

@interface NewViewController : UITableViewController
{
    NSArray *arrayList;

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

}

@property(nonatomic, retain)NSArray *arrayList;

@end

В 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

Таким образом, мы можем передавать данные с одного диспетчера представлений на другой контроллер представления ...

8
ответ дан Sabs 15 August 2018 в 18:20
поделиться

Вы можете сохранить данные в делегате приложения, чтобы получить доступ к ним через контроллеры представлений в своем приложении. Все, что вам нужно сделать, это создать общий экземпляр делегата приложения

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

. Для примера

, если вы объявите NSArray object *arrayXYZ, вы можете получить к нему доступ в любом контроллере представления appDelegate.arrayXYZ

10
ответ дан Sangram S. 15 August 2018 в 18:20
поделиться

Создайте свойство на следующем view controller .h и определите getter и setter.

Добавьте это property в NextVC.h на nextVC

@property (strong, nonatomic) NSString *indexNumber;

Добавить

@synthesize indexNumber; в NextVC.m

И последний

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

vc.indexNumber=@"123";

[self.navigationController vc animated:YES];
13
ответ дан Sport 15 August 2018 в 18:20
поделиться

Передача данных между FirstViewController в SecondViewController, как показано ниже

Например:

Значение FirstViewController String как

StrFirstValue = @"first";

, поэтому мы можем передать это значение во втором класс, используя нижеследующий шаг

1> Нам нужно вырезать строковый объект в файле SecondViewController.h

NSString *strValue;

2> Нужно объявить свойство, как показано ниже, в декларации в .h файле

@property (strong, nonatomic)  NSString *strSecondValue;

3> Нужно синтезировать это значение в файле FirstViewController.m ниже объявления заголовка

@synthesize strValue;

и в FirstViewController.h:

@property (strong, nonatomic)  NSString *strValue;

4> В FirstViewController, из которого мы переходим ко второму виду, напишите ниже код в этом методе.

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

[secondView setStrSecondValue:StrFirstValue];

[self.navigationController pushViewController:secondView animated:YES ];
16
ответ дан SpyZip 15 August 2018 в 18:20
поделиться
  • 1
    После того, как вы вошли в SecondViewController, как вы передаете данные обратно в FirstViewController? – bruno 5 January 2015 в 14:01
  • 2
    Сумасшедшие переменные имен! – Itachi 16 August 2017 в 03:55

Существует множество способов сделать это, и важно выбрать правильный. Вероятно, одним из самых больших архитектурных решений является то, как код модели будет доступен или доступен во всем приложении.

Я написал сообщение в блоге об этом некоторое время назад: Общий код модели , Ниже приведен краткий обзор:

Общие данные

. Один из подходов состоит в том, чтобы совместно использовать указатели на объекты модели между контроллерами представления.

  • Итерация с принудительной передачей на контроллерах представления (в навигаторе или панели управления панелью) для установки данных
  • Установите данные в файле подготовки (если раскадровки) или init (если программно)

Поскольку подготовка к segue является наиболее распространенной, здесь приведен пример:

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

Независимый доступ

Другой подход заключается в том, чтобы обрабатывать полный экран данных одновременно, и вместо того, чтобы связывать контроллеры представлений друг с другом, каждый из них контролирует один источник данных, который они могут получить независимо.

Наиболее распространенный способ, которым я видел это, - это экземпляр singleton . Поэтому, если ваш объект singleton был DataAccess, вы можете сделать следующее в методе viewDidLoad для UIViewController:

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

. Существуют дополнительные инструменты, которые также помогают передавать данные:

  • Замечание о ключевом значении
  • NSNotification
  • Основные данные
  • NSFetchedResultsController
  • Источник данных

] Основные данные

Хорошая вещь в Core Data заключается в том, что она имеет обратные отношения. Поэтому, если вы хотите просто предоставить NotesViewController объект заметок, который вы можете использовать, поскольку он будет иметь обратную связь с чем-то другим, например, с ноутбуком. Если вам нужны данные на ноутбуке в NotesViewController, вы можете вернуться к графику объекта, выполнив следующие действия:

let notebookName = note.notebook.name

Подробнее об этом читайте в моем сообщении в блоге: Общий код модели

46
ответ дан Super Developers 15 August 2018 в 18:20
поделиться

Swift

Есть тонны и тонны объяснений здесь и вокруг StackOverflow, но если вы новичок, просто пытающийся получить что-то основное для работы, попробуйте посмотреть этот учебник YouTube (это помогло мне, наконец, понять, как это сделать).

Передача данных вперед к следующему контроллеру View

Ниже приведен пример, основанный на видео. Идея состоит в том, чтобы передать строку из текстового поля в First View Controller на метку в Second View Controller.

Создать раскладку раскладки в Interface Builder.

First View Controller

Код для первого контроллера просмотра -

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

}

Контроллер второго взгляда

И код для второго контроллера просмотра -

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
    }

}

Не забывайте

  • Крючок (f5) и UILabel.
  • Установите первый и второй контроллеры просмотра в соответствующие файлы Swift в IB.

Передача данных назад к предыдущему контроллеру View

Чтобы передать данные с второго контроллера представления на первый контроллер представления, вы используете протокол и делегат . Этот видеоролик - очень четкая прогулка по этому процессу:

Ниже приведен пример, основанный на видео (с некоторыми изменениями).

Создайте раскладной план в Interface Builder. Опять же, чтобы сделать segue, вы просто управляете перетаскиванием с кнопки на второй контроллер просмотра. Установите идентификатор segue на showSecondViewController. Кроме того, не забудьте подключить выходы и действия, используя имена в следующем коде.

First View Controller

Код для первого контроллера просмотра -

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

Обратите внимание на использование нашего пользовательского протокола DataEnteredDelegate.

Второй просмотр контроллера и протокола

Код для второго контроллера просмотра -

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

Обратите внимание, что protocol находится вне класса View Controller.

Вот и все. Запустив приложение, вы сможете отправлять данные с второго контроллера представления на первый.

132
ответ дан Suragch 15 August 2018 в 18:20
поделиться
  • 1
    Учитывая некоторые из последних обновлений Swift, это все еще распространенная модель для реализации? – piofusco 8 December 2015 в 08:35
  • 2
    Большинство всех обновлений Swift, которые я видел, были относительно незначительными синтаксическими изменениями, а не изменениями в том, как данные передаются между контроллерами представлений. Если я узнаю о каких-либо серьезных изменениях, я обновлю свой ответ. – Suragch 8 December 2015 в 12:23
  • 3
    offtopic - iOS имеет такой уродливый способ передать параметры новым контроллерам представлений, невероятно - вам нужно устанавливать параметры не в том месте, где вы делаете вызов, а в каком-то другом. Android имеет лучший подход в этом отношении - когда вы начинаете Activity, вы можете передавать любые данные (ну, почти) с помощью своего начального намерения. Легко. Не нужно бросать или что-то в этом роде. Передача возвращаемых значений обратно вызывающему абоненту тоже важна, нет необходимости делегировать. Конечно, можно использовать уродливые подходы тоже, проблем нет)) – Mixaz 1 April 2016 в 15:51
  • 4
    @Himanshu, сначала получите ссылку на второй контроллер представления. Затем обновите общедоступную переменную, содержащуюся в ней. – Suragch 30 July 2016 в 15:26
  • 5
    @Мед. Я думаю, что слово «делегировать» вызывает смущение. Позвольте мне использовать слово «рабочий». «Рабочий» (контроллер первого вида) делает все, что угодно "босса" (контроллер второго представления) говорит ему об этом. "Босс" не знает, кто его "рабочий" будет; это может быть кто угодно. Поэтому в первом представлении контроллера («рабочий» класс) говорится, что я буду вашим «рабочим». Вы говорите мне, что писать на лейбле, и я сделаю это для вас. Таким образом, secondViewController.delegate = self означает «я согласен быть работником босса». См. этот ответ для другого примера и более подробного объяснения. – Suragch 26 September 2016 в 06:44

В настоящее время я вношу свой вклад в решение этой проблемы с открытым исходным кодом с помощью проекта MCViewFactory, который можно найти здесь:

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

Идея имитирует парадигму намерений Android, используя глобальную фабрику для управления просмотром, на который вы смотрите, и используя «намерения» для переключения и передачи данных между представлениями. Вся документация находится на странице github, но вот некоторые основные моменты:

Вы настраиваете все свои представления в файлах .XIB и регистрируете их в делегате приложения при инициализации фабрики.

// Register activities

MCViewFactory *factory = [MCViewFactory sharedFactory];

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

Теперь, в вашем VC, в любое время, когда вы хотите перейти на новый VC и передать данные, вы создаете новое намерение и добавляете данные в свой словарь (savedInstanceState). Затем просто установите текущее намерение фабрики:

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

. Все ваши представления, которые соответствуют этому, должны быть подклассами MCViewController, которые позволяют вам переопределить новый метод onResume:, позволяющий вам получить доступ к данные, которые вы прошли.

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

Надеюсь, что некоторые из вас считают это решение полезным / интересным.

16
ответ дан user 15 August 2018 в 18:20
поделиться
  • 1
    Тогда все объекты контроллера могли бы получить / установить все зарегистрированные словари в любых областях? Снизьте это. – Itachi 16 August 2017 в 03:53

В OP не упоминались контроллеры представлений, но так много ответов, что я хотел подслушивать то, что некоторые из новых функций LLVM позволяют сделать это проще, когда вы хотите передавать данные с одного контроллера вида на другой, а затем получая некоторые результаты назад.

Разделительные раскладки, блоки ARC и LLVM делают это проще, чем когда-либо для меня. Некоторые ответы выше упомянутых раскадровки и segue уже, но все еще опирались на делегацию. Определение делегатов, безусловно, работает, но некоторым людям легче найти указатели или кодовые блоки.

С помощью UINavigators и segues есть простые способы передачи информации контроллеру подчиненного и возврату информации. ARC делает простые указатели на вещи, полученные из NSObjects, поэтому, если вы хотите, чтобы подчиненный контроллер добавлял / изменял / модифицировал некоторые данные для вас, передайте ему указатель на изменяемый экземпляр. Блоки упрощают прохождение, поэтому, если вы хотите, чтобы подчиненный контроллер вызывал действие на вашем контроллере более высокого уровня, передайте ему блок. Вы определяете блок, чтобы принять любое количество аргументов, которое имеет смысл для вас. Вы также можете разработать API для использования нескольких блоков, если это лучше всего подходит.

Вот два тривиальных примера клея segue. Первый - это простой показ одного параметра, переданного для ввода, второй для вывода.

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

Этот второй пример показывает передачу блока обратного вызова для второго аргумента. Мне нравится использовать блоки, потому что он держит соответствующие детали близко друг к другу в источнике - источник более высокого уровня.

// 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
ответ дан WeakPointer 15 August 2018 в 18:20
поделиться
[Д0] 1. Создайте экземпляр First View Controller во втором контроллере просмотра и создайте его свойство @property (nonatomic,assign).

2. Назначьте экземпляр SecondviewController этого контроллера вида.

2. Когда вы закончите операцию выбора, скопируйте массив в первый вид контроллера, Когда u выгрузит SecondView, FirstView будет хранить данные массива.

Надеюсь, что это поможет.

18
ответ дан Irfan 15 August 2018 в 18:20
поделиться
  • 1
    Я не верю, что это правильный путь, поскольку он создает очень ограниченную связь между контроллерами представлений. На самом деле не прилипает к MVC. – Matt Price 28 May 2012 в 15:49
  • 2
    Если вы хотите строго следовать MVC, используйте NSNotificationCenter , метод может быть вызван из ViewControllerA в ViewControllerB, проверьте этот , он может помочь u – kaar3k 4 June 2012 в 15:07
46
ответ дан Super Developers 15 August 2018 в 18:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: