[iphone] Storyboard-AppDelegate의 ViewController 참조

다음 시나리오를 고려하십시오. 스토리 보드 기반 앱이 있습니다. 스토리 보드에 ViewController 개체를 추가하고이 ViewController에 대한 클래스 파일을 프로젝트에 추가하고 IB ID 검사기에서 새 클래스의 이름을 지정합니다. 이제 AppDelegate에서 프로그래밍 방식으로이 ViewController를 어떻게 참조할까요? 관련 클래스를 사용하여 변수를 만들고 IBOutlet 속성으로 변경했지만 코드에서 새 ViewController를 참조 할 수있는 방법이 없습니다. 연결을 ctrl-drag하려는 시도가 작동하지 않습니다. .

즉, AppDelegate 내에서 다음과 같이 기본 ViewController에 도달 할 수 있습니다.

(MyViewController*) self.window.rootViewController

하지만 스토리 보드에 포함 된 다른 ViewController는 어떻습니까?



답변

에 대한 문서 를 살펴보십시오 -[UIStoryboard instantiateViewControllerWithIdentifier:]. 이를 통해 IB Attributes Inspector에서 설정 한 식별자를 사용하여 스토리 보드에서 뷰 컨트롤러를 인스턴스화 할 수 있습니다.

여기에 이미지 설명 입력

예제 코드를 추가하기 위해 편집 됨 :

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                         bundle: nil];

MyViewController *controller = (MyViewController*)[mainStoryboard
                    instantiateViewControllerWithIdentifier: @"<Controller ID>"];


답변

XCode5 를 사용한다면 다른 방법으로해야합니다.

  • 당신의 선택 UIViewController의를UIStoryboard
  • 로 이동 Identity Inspector우측 상단 창에서
  • 체크 Use Storyboard ID박스 확인
  • Storyboard ID필드에 고유 ID를 작성하십시오.

그런 다음 코드를 작성하십시오.

// Override point for customization after application launch.

if (<your implementation>) {
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main"
                                                             bundle: nil];
    YourViewController *yourController = (YourViewController *)[mainStoryboard
      instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
    self.window.rootViewController = yourController;
}

return YES;


답변

일반적으로 시스템은 스토리 보드를 사용하여 뷰 컨트롤러 인스턴스화를 처리해야합니다. 원하는 것은 self.window.rootViewController뷰 컨트롤러를 초기화 하는 것과 반대로에 대한 참조를 잡아서 viewController 계층을 탐색하는 것입니다. 이는 스토리 보드를 올바르게 설정 한 경우 이미 올바르게 초기화되어야합니다.

따라서 귀하 rootViewController가 UINavigationController이고 상위 뷰 컨트롤러로 무언가를 보내고 싶다면 AppDelegate의 didFinishLaunchingWithOptions다음 과 같이 할 수 있습니다 .

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;

Swift에서 매우 유사하다면 :

let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data

스토리 보드가로드되는 일반적인 방식을 우회하고 전체 스토리 보드를 직접로드하려는 경우가 아니라면 앱 델리게이트의 스토리 보드 ID를 사용하여 뷰 컨트롤러를 초기화해서는 안됩니다. AppDelegate에서 장면을 초기화해야한다면 뭔가 잘못되었을 가능성이 큽니다. 어떤 이유로 든 스택 아래에있는 뷰 컨트롤러에 데이터를 보내고 싶어한다고 상상하면 AppDelegate가 데이터를 설정하기 위해 뷰 컨트롤러 스택에 도달해서는 안됩니다. 그것은 사업이 아닙니다. 비즈니스는 rootViewController입니다. rootViewController가 자체 자식을 처리하게하십시오! 따라서 info.plist 파일에서 참조를 제거하여 시스템의 일반적인 스토리 보드로드 프로세스를 우회하는 경우 기껏해야 rootViewController를 다음을 사용하여 인스턴스화합니다.instantiateViewControllerWithIdentifier:, UINavigationController와 같은 컨테이너 인 경우 루트 일 수 있습니다. 피하고 싶은 것은 스토리 보드에서 이미 인스턴스화 한 뷰 컨트롤러를 인스턴스화하는 것입니다. 이것은 내가 많이 보는 문제입니다. 요컨대, 나는 받아 들인 대답에 동의하지 않습니다. 포스터가 info.plist에서 스토리 보드로드를 제거하는 것을 의미하지 않는 한 올바르지 않습니다. 그렇지 않으면 2 개의 스토리 보드를로드하게되므로 말이되지 않습니다. 시스템이 루트 씬을 초기화하고 창에 할당했기 때문에 메모리 누수가 아닌 것 같습니다.하지만 여러분이 와서 다시 인스턴스화하고 다시 할당했습니다. 귀하의 앱은 시작이 매우 좋지 않습니다!


답변

    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
    self.window.rootViewController = [storyboard instantiateInitialViewController];


답변