dismissModalViewController И передать данные обратно - PullRequest
84 голосов
/ 01 июня 2011

У меня есть два контроллера представления, firstViewController и secondViewController .Я использую этот код для переключения на свой 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];

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

Ответы [ 4 ]

142 голосов
/ 01 июня 2011

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

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

#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: События запуска по нескольким контроллерам представления из потока в приложении:

РЕДАКТИРОВАТЬ:

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

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
}
40 голосов
/ 08 ноября 2013

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

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

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

self.somethingHappenedInVC2(@"Hello!");

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

РЕДАКТИРОВАТЬ - Улучшенный пример

Допустим, у нас есть 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);
}

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

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

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

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

4 голосов
/ 01 июня 2011

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

2 голосов
/ 01 июня 2011

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

...