ReturnModalViewController И передать данные обратно

У меня есть два контроллера представления, firstViewController и secondViewController. Я использую этот код для переключения на мой второй монитор (я также передаю ему строку):

secondViewController *second = [[secondViewController alloc] initWithNibName:nil bundle:nil];

second.myString = @"This text is passed from firstViewController!";

second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

[self presentModalViewController:second animated:YES];

[second release];

Затем я использую этот код в secondViewController для переключения на firstViewController:

[self dismissModalViewControllerAnimated:YES];

Все это прекрасно работает. Мой вопрос: как передать данные в firstViewController? Я хотел бы передать другую строку в firstViewController из secondViewController.

Я ценю любую помощь. Спасибо, ребята.

Ответ 1

Вам нужно использовать протоколы делегатов... Вот как это сделать:

Объявить протокол в файле заголовка secondViewController. Он должен выглядеть следующим образом:

#import <UIKit/UIKit.h>

@protocol SecondDelegate <NSObject>
-(void)secondViewControllerDismissed:(NSString *)stringForFirst
@end


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;

Не забудьте синтезировать myDelegate в файле своей реализации (SecondViewController.m):

@synthesize myDelegate;

В вашем файле заголовка FirstViewController подписаться на протокол SecondDelegate, выполнив следующее:

#import "SecondViewController.h"

@interface FirstViewController:UIViewController <SecondDelegate>

Теперь, когда вы создаете экземпляр SecondViewController в FirstViewController, вы должны сделать следующее:

// If you're using a view controller built with Interface Builder.
SecondViewController *second = [[SecondViewController alloc] initWithNibName:"SecondViewController" bundle:[NSBundle mainBundle]];
// If you're using a view controller built programmatically.
SecondViewController *second = [SecondViewController new]; // Convenience initializer that uses alloc] init]
second.myString = @"This text is passed from firstViewController!";
second.myDelegate = self;
second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:second animated:YES];
[second release];

Наконец, в файле реализации вашего первого контроллера представления (FirstViewController.m) реализуется метод SecondDelegate для secondViewControllerDismissed:

- (void)secondViewControllerDismissed:(NSString *)stringForFirst
{
    NSString *thisIsTheDesiredString = stringForFirst; //And there you have it.....
}

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

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!"];
}
[self dismissModalViewControllerAnimated:YES];

Протоколы делегатов ЧРЕЗВЫЧАЙНЫ, ЧРЕЗВЫЧАЙНЫ, Чрезвычайно полезны. Вам будет полезно ознакомиться с ними:)

NSNotifications - это еще один способ сделать это, но, как наилучшая практика, я предпочитаю использовать его, когда хочу общаться через несколько viewControllers или объектов. Вот ответ, который я опубликовал ранее, если вам интересно использовать NSNotifications: Увольнение событий через несколько диспетчеров просмотра из потока в appdelegate

EDIT:

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

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];

Это означает, что ваша реализация метода SecondDelegate внутри вашего firstViewController будет выглядеть следующим образом:

- (void) secondViewControllerDismissed:(NSString*)stringForFirst argument2:(NSObject*)inObject1 argument3:(NSObject*)inObject2
{
    NSString thisIsTheDesiredString = stringForFirst;
    NSObject desiredObject1 = inObject1;
    //....and so on
}

Ответ 2

Я мог бы быть неуместным здесь, но я начинаю много предпочитать синтаксис блока очень подробному подходу делегата/протокола. Если вы делаете vc2 из vc1, у вас есть свойство на vc2, которое вы можете установить из vc1, который является блоком!

@property (nonatomic, copy) void (^somethingHappenedInVC2)(NSString *response);

Затем, когда что-то происходит в vc2, о котором вы хотите сообщить vc1, просто выполните блок, который вы определили в vc1!

self.somethingHappenedInVC2(@"Hello!");

Это позволяет вам отправлять данные с vc2 обратно в vc1. Также как магия. IMO, это намного проще/чище, чем протоколы. Блоки являются удивительными и должны быть охвачены как можно больше.

EDIT - улучшенный пример

Скажем, у нас есть mainVC, который мы хотим представить modalVC поверх временно, чтобы получить некоторый вклад от пользователя. Чтобы представить этот modalVC из mainVC, нам нужно выделить/инициализировать его внутри mainVC. Довольно простой материал. Хорошо, когда мы создаем этот объект modalVC, мы также можем установить на нем свойство блока, которое позволяет нам легко обмениваться данными между обоими объектами vc. Поэтому давайте рассмотрим пример сверху и поместим свойство follwing в .h файл modalVC:

 @property (nonatomic, copy) void (^somethingHappenedInModalVC)(NSString *response);  

Затем в нашем mainVC после выделения /init 'd нового объекта modalVC вы устанавливаете свойство блока modalVC следующим образом:

ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}

Итак, мы просто устанавливаем свойство block и определяем, что происходит, когда этот блок выполняется.

Наконец, в нашем modalVC мы могли бы иметь tableViewController, который поддерживается массивом dataSource строк. После выбора строки мы можем сделать что-то вроде этого:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }

И, конечно, каждый раз, когда мы выбираем строку в modalVC, мы собираемся получить вывод консоли из нашей строки NSLog в mainVC. Надеюсь, что это поможет!

Ответ 3

hmm, найдите центр уведомлений и передайте информацию в уведомлении. вот яблоки берут на себя  - Я принимаю этот подход лично, если у кого-то нет других предложений.

Ответ 4

Определите протокол делегата во втором контроллере представления и сделайте первый делегат второго.