두 개의 뷰 컨트롤러, 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];
이 모든 것이 잘 작동합니다. 내 질문은 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로 가져옵니다. 도움이 되었기를 바랍니다.
답변
흠, 알림 센터를 찾아 알림에 정보를 전달합니다. 여기에 사과가 있습니다.
다른 제안이없는 한 개인적으로이 접근 방식을 취합니다.
답변
두 번째 뷰 컨트롤러에서 델리게이트 프로토콜을 정의하고 첫 번째를 두 번째의 델리게이트로 만듭니다.