[iphone] dismissModalViewController 및 데이터 다시 전달

두 개의 뷰 컨트롤러, firstViewControllersecondViewController가 있습니다. 이 코드를 사용하여 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에 데이터를 어떻게 전달합니까? secondViewController에서 firstViewController로 다른 문자열을 전달하고 싶습니다.



답변

위임 프로토콜을 사용해야합니다 … 방법은 다음과 같습니다.

secondViewController의 헤더 파일에서 프로토콜을 선언하십시오. 다음과 같이 표시되어야합니다.

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;
}

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

구현 (SecondViewController.m) 파일에서 myDelegate를 합성하는 것을 잊지 마십시오.

@synthesize myDelegate;

FirstViewController의 헤더 파일에서 다음을 수행하여 SecondDelegate 프로토콜을 구독하십시오.

#import "SecondViewController.h"

@interface FirstViewController:UIViewController <SecondDelegate>

이제 FirstViewController에서 SecondViewController를 인스턴스화 할 때 다음을 수행해야합니다.

// 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)의 구현 파일에서 secondViewControllerDismissed에 대한 SecondDelegate의 메서드를 구현합니다.

- (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는이를 수행하는 또 다른 방법이지만 모범 사례로서 여러 viewController 또는 개체간에 통신하려는 경우 사용하는 것을 선호합니다. NSNotifications 사용에 대해 궁금한 경우 이전에 게시 한 답변은 다음과 같습니다 . appdelegate의 스레드에서 여러 뷰 컨트롤러에 걸쳐 이벤트 발생

편집하다:

여러 인수를 전달하려는 경우 닫기 전 코드는 다음과 같습니다.

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

즉, firstViewController 내부의 SecondDelegate 메서드 구현이 다음과 같이 보일 것입니다.

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


답변

여기서 벗어날 수는 있지만 매우 장황한 델리게이트 / 프로토콜 접근 방식보다 블록 구문을 선호하기 시작했습니다. vc1에서 vc2를 만들면 블록 인 vc1에서 설정할 수있는 vc2의 속성을 가지세요!

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

그런 다음 vc2에서 vc1에 알리고 싶은 일이 발생하면 vc1에서 정의한 블록을 실행하십시오!

self.somethingHappenedInVC2(@"Hello!");

이를 통해 vc2에서 vc1로 데이터를 다시 보낼 수 있습니다. 마법처럼. IMO, 이것은 프로토콜보다 훨씬 쉽고 / 깨끗합니다. 블록은 굉장하며 가능한 한 많이 수용해야합니다.

편집-개선 된 예

사용자로부터 입력을 받기 위해 일시적으로 modalVC를 표시하려는 mainVC가 있다고 가정 해 보겠습니다. mainVC에서 해당 modalVC를 표시하려면 mainVC 내부에 할당 / 초기화해야합니다. 아주 기본적인 것들. 이 modalVC 객체를 만들 때 두 vc 객체간에 쉽게 통신 할 수 있도록 블록 속성을 설정할 수도 있습니다. 따라서 위의 예를 들어 modalVC의 .h 파일에 다음 속성을 입력 해 보겠습니다.

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

그런 다음 mainVC에서 새 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에서 문자열의 dataSource 배열로 지원되는 tableViewController를 가질 수 있습니다. 행 선택이 이루어지면 다음과 같이 할 수 있습니다.

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

물론 modalVC에서 행을 선택할 때마다 NSLog 라인에서 콘솔 출력을 mainVC로 가져옵니다. 도움이 되었기를 바랍니다.


답변

흠, 알림 센터를 찾아 알림에 정보를 전달합니다. 여기에 사과가 있습니다.
다른 제안이없는 한 개인적으로이 접근 방식을 취합니다.


답변

두 번째 뷰 컨트롤러에서 델리게이트 프로토콜을 정의하고 첫 번째를 두 번째의 델리게이트로 만듭니다.


답변