Storyboard-AppDelegate의 ViewController 참조


122

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

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

(MyViewController*) self.window.rootViewController

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


이 대답을 확인하십시오 . 빠르지 만 언어는 비슷합니다.
Borzh

답변:


165

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

여기에 이미지 설명 입력

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

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

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

안녕 로빈, 감사합니다! 이 문서를 살펴 보았지만 인스턴스화 및 초기화라는 단어가 섞여 있습니다 ... 이로 인해 (귀하의 지침을 따른 후 :) (답글에 코드 서식이 부족합니다 ...) UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName : @ "MainStoryboard"번들 : nil]; MyViewController * thisController = (MyViewController *) [mainStoryboard instantiateViewControllerWithIdentifier : @ "myvc"];
Matthias D

나는 이것을보고있는 모든 사람들을 위해 서식을 지정하여 답변에 예제 코드를 추가했습니다.
Robin Summerhill 2011

24
범용 앱을 만드는 경우 MainStoryboard_iPhone / MainStoryboard_iPad를 사용해야합니다. 그렇지 않으면 충돌이 발생합니다.
roocell 2011

16
델리게이트 내에서 다음과 같이 info.plist에 의해로드 된 스토리 보드 인스턴스에 액세스 할 수 있습니다. [[[self window] rootViewController] storyboard] 문서에 따르면 "뷰 컨트롤러가 시작된 스토리 보드"를 반환합니다. (또는 스토리 보드에서 오지 않았다면 nil ). 해당 UIStoryboard *에서 @RobinSummerhill이 언급 한 인스턴스화 호출을 사용할 수 있습니다. Storyboard 는 필요 에 따라 viewController ( scenes ) 의 새 인스턴스를 인스턴스화 하고 이전에 본 항목을 재사용하지 않습니다.
Tad Bumcrot 2012

6
나는 OP가 현재 실행중인 vc에서 얻는 방법을 알고 싶어한다고 생각합니다. 로드하는 방법이 아닙니다. 그가 설명 했듯이 정확히이 self.window.rootViewController 를 말할 수 있었지만 이제는 더 이상 말할 수 없습니다.
Fattie 2014 년

41

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;

4
내가 알고 그것을 시도 할 수 있었던 한 이것은 업데이트 된 답변입니다.
gnclmorais 2013 년

스토리 보드의 이름은 확장자가없는 파일 이름이므로 이러한 방식으로 프로젝트를 설정 한 경우 "Main_iPhone"또는 "Main_iPad"가 될 수도 있습니다.
Brian White

로그인 후 어떻게 원래 rootViewController로 다시 전환합니까? 적어도 iOS 7 및 Xcode 5.0.2에 대한 내 지식은 루트 뷰 컨트롤러를 다시 변경하면 즉시 애니메이션없이 뷰 계층 구조를 전환합니다. UX 팀은 적은 비용으로 코더를 죽였습니다.
lol

Swift를 사용하여 어떻게 할 수 있습니까?
Leo Dabus 2014

8

일반적으로 시스템은 스토리 보드를 사용하여 뷰 컨트롤러 인스턴스화를 처리해야합니다. 원하는 것은 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 개의 스토리 보드를로드하게되므로 말이되지 않습니다. 시스템이 루트 씬을 초기화하고 창에 할당했기 때문에 메모리 누수가 아닌 것 같습니다.하지만 여러분이 와서 다시 인스턴스화하고 다시 할당했습니다. 귀하의 앱은 시작이 매우 좋지 않습니다!


0
    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
    self.window.rootViewController = [storyboard instantiateInitialViewController];
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.