문제

누구 든지이 뿌리를 알고 있습니다 View Controller's viewDidLoad 출시 당시 두 번 호출됩니까? 그것은 나를 미쳤다!

처음부터 스택 추적이 있습니다 viewDidLoad:

#0  0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1  0x3097548f in -[UIViewController view]
#2  0x00002734 in -[RootViewController initWithCoder:] at RootViewController.m:39
#3  0x30ab5ce4 in -[UIClassSwapper initWithCoder:]
#4  0x30514636 in _decodeObjectBinary
#5  0x30514035 in _decodeObject
#6  0x30ab5a1d in -[UIRuntimeConnection initWithCoder:]
#7  0x30514636 in _decodeObjectBinary
#8  0x30515f27 in -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
#9  0x305163b0 in -[NSArray(NSArray) initWithCoder:]
#10 0x30514636 in _decodeObjectBinary
#11 0x30514035 in _decodeObject
#12 0x30ab4dde in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#13 0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#14 0x308f85f1 in -[UIApplication _loadMainNibFile]
#15 0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#16 0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#17 0x308fad82 in -[UIApplication sendEvent:]
#18 0x309013e1 in _UIApplicationHandleEvent
#19 0x32046375 in PurpleEventCallback
#20 0x30245560 in CFRunLoopRunSpecific
#21 0x30244628 in CFRunLoopRunInMode
#22 0x308f930d in -[UIApplication _run]
#23 0x309021ee in UIApplicationMain
#24 0x000022e4 in main at main.m:14

그리고 두 번째로 :

#0  0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1  0x30ab50cd in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#2  0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#3  0x308f85f1 in -[UIApplication _loadMainNibFile]
#4  0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#5  0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#6  0x308fad82 in -[UIApplication sendEvent:]
#7  0x309013e1 in _UIApplicationHandleEvent
#8  0x32046375 in PurpleEventCallback
#9  0x30245560 in CFRunLoopRunSpecific
#10 0x30244628 in CFRunLoopRunInMode
#11 0x308f930d in -[UIApplication _run]
#12 0x309021ee in UIApplicationMain
#13 0x000022e4 in main at main.m:14
도움이 되었습니까?

해결책

기이한. 나는이 특별한 경우를 보지 못했지만 일반적으로 ViewDidload를 여러 번 호출 할 수 있다고 가정해야합니다. 컨트롤러가로드 된 것을 참조하는 NIB 파일이있을 때마다 호출됩니다.

펜촉형이 하나만있는 간단한 앱의 경우 발생하지 않아야합니다. 그러나보기 컨트롤러를로드하고 내릴 수있는보다 복잡한 앱에서는 항상 발생합니다.

다른 팁

앱이 처음 시작될 때 동일한 문제가있었습니다. 내가 찾은 것은 MainWindow.xib 파일에서 앱 대의원의 두 가지를 모두 설정하고 있다는 것입니다. viewController 콘센트와 내 창문 rootViewController 루트보기 컨트롤러에 대한 콘센트. Xcode에서보기 기반 프로젝트 파일을 빌드하면 앱 대의원의 didFinishLaunchingWithOptions 다음과 같이 사전 인구가 제공됩니다.

self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;

나는 그것을 믿는다 self.viewController ivar는 이전에 MainWindow.xib에서 인스턴스화됩니다 didFinishLaunchingWithOptions 호출됩니다. 그런 다음 위의 사전 인구 코드가 창을 설정합니다 rootViewController. 따라서 함께하면 rootViewController MainWindow.xib 파일의 창에 대한 콘센트는 루트보기 컨트롤러가 실제로 두 번 생성되어 Window의 루트보기 컨트롤러로 두 번 추가됩니다.

나는 약간의 디버깅을했고 여기에 내가 찾은 것은 ViewController 로딩 순서 :

initWithNibName:bundle:     self = <original instance>, retainedOutlet = 0x0  
loadView >>>                self = <original instance>, retainedOutlet = 0x0  
      initWithCoder:        self = <coder instance>,    retainedOutlet = 0x0  
      initWithCoder:        self = <coder instance>,    retainedOutlet = 0x0  
      setView:              self = <original instance>, retainedOutlet = 0x0  
      setRetainedOutlet:    self = <original instance>, retainedOutlet = 0x1613c40  
      viewDidLoad           self = <coder instance>,    retainedOutlet = 0x0  
      awakeFromNib          self = <coder instance>,    retainedOutlet = 0x0  
loadView <<<  
viewDidLoad                 self = <original instance>, retainedOutlet = 0x1613c40  
viewWillAppear:             self = <original instance>, retainedOutlet = 0x1613c40  
dealloc                     self = <coder instance>,    retainedOutlet = 0x0
viewDidAppear:              self = <original instance>, retainedOutlet = 0x1613c40

로드 뷰 방법 중에 initWithCoder: 호출되고 새 사본이 있습니다 viewController 생성됩니다. 이것은 몇 가지 방법으로 전달되는 것입니다 (: viewDidLoad). 사본은 나중에 거래로 전화를 걸어 파괴됩니다. 좋은 소식은이 사본에서 유지 된 콘센트가 구성되지 않으므로 변수를 초기화하고 다른 방법을 호출 해야하는지 알 수 있도록 테스트로 사용하고 가장 중요한 것은 Dealloc 동안 객체를 해제하고 파괴 해야하는 경우 가장 중요한 것입니다.

주요 테이크 아웃 : 진짜 viewController 유지 될 것입니다 IBOutlet 속성이 구성되었습니다. 여러 번 호출되는 재정의 방법이라면 유지 된 중 하나를 확인하십시오. IBOutlet 속성 NULL. 그들이 있다면 NULL, 그런 다음 즉시 돌아옵니다.

왜 이런 식으로 일어나고 있는지에 대한 단서가 있습니까?

이것의 부작용 : 당신은 사용할 수 없습니다 awakeFromNib 확실하게.

ViewDidload가 한 번만 호출 될 것이라고 가정 할 수 없습니다. 객체를 초기화하고 보증을 원하는 경우 init 메소드에서 또는 AwakefromNib 메소드에서 NIB 파일에서로드중인 경우 초기화를 수행하십시오.

나는 비슷한 문제가 있었고 그것은 내 XIB 파일을 바꾸는 결과였습니다. ViewController 클래스 (파일 소유자). 그렇게하지 마십시오. 실제로 XML 내부에서 잘못 정의 된 견해와 대표가 잘못 정의되어 복구 할 수 없었습니다. 한편, 나는 나의 새로운 VC로 여겨지는 원래 VC로드에 대한 언급을 가졌다. 나는 부모가 스스로를 재현 한 다음 VC를 실제로 호출하려고 시도했다고 생각합니다. 기본적으로 X2가있는 VC에 간접적 인 재귀를 만들었습니다. viewDidLoad 내 흔적의 항목.

x2에 대한 유효한 이유가 없다고 생각합니다. viewDidLoad 그것은 창세기이므로 잘못된 가정 전 조건으로 다른 초기화를 호출 할 수 있습니다. X2 ViewDidload를 볼 때마다, 그것은 내 부분에 대한 코딩 오류였습니다.

그 이상의 유효한 이유가있는 경우 viewDidLoad 전화, 누군가 (Apple Dev가 듣고 있습니까) 기술적으로 자세히 설명합니다. 저는 몇 달 동안 그 답을 찾고 있습니다.

나는이 문제가 있었지만 그것을 고칠 수있었습니다.

해결책:

두 번로드하는 View Controller 클래스의 이름을 바꿉니다.

세부:

이름을 바꾸고 새 이름을 완전히 새로운 것으로 만드십시오. 파일의 이름 바꾸기 로드 트 와이스 문제를 중지하지 않습니다. 새로운 프로젝트를 만드는 (다른 사람들이 제안한대로)는 과잉 일 수 있습니다. 최소한 더 간단한 솔루션을 먼저 시도하십시오! 대상 VC 클래스의 이름을 바꿉니다.

힌트: 수업의 이름을 바꾸면 문제가 해결되면 해당 클래스에 대한 모든 참조를 업데이트해야합니다. 프로젝트 전체 찾기에 명령+Shift+F를 사용하여 속도를 높일 수 있습니다.

나는 다시 디자인하는 것과 같은 문제에 부딪쳤다. ViewController 처음부터 XIB 파일을 제거하고 클래스를 재사용 할 수 있도록합니다. 나는이 두 번째를 가졌다 ViewController 받을 인스턴스 viewDidLoad 메시지 다음으로 거래 메시지가 이어집니다.

나는 이것이 결과라는 것을 알았다 loadView 메소드에서 재정의되지 않았습니다 ViewController. 기본값 loadView ~라고 불리는 awakeFromNib, 이랑 nibName 속성은 클래스 이름으로 설정되었습니다. 프로젝트에서 XIB 파일을 제거했지만 여전히 시뮬레이터의 응용 프로그램 디렉토리에있었습니다.

따라서 시뮬레이터의 내용과 설정을 재설정하여 두 번째를 제거 할 수 있습니다. viewDidLoad, 더 좋은 방법은 단지 재정의하는 것일 수 있습니다 loadView 이와 같이:

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; 
}

문서를 고려하면 의미가 있습니다. UIViewController's 속성보기 :

이 속성에 액세스하고 그 값이 현재 NIL 인 경우 View 컨트롤러는 자동으로 호출됩니다. loadView 메소드 및 결과보기를 반환합니다. 기본값 loadView메소드는보기 컨트롤러 (있는 경우)와 관련된 NIB 파일에서 뷰를로드하려고 시도합니다. View Controller가 관련 NIB 파일이없는 경우 loadView 방법을 사용하고 사용하여 루트보기 및 모든 하위 뷰를 만듭니다.

제 경우에는 실제로 rootViewController를 두 번 할당 한 것을 알지 못했습니다.

application:didFinishLaunchingWithOptions: 그리고 applicationDidBecomeActive:

이것에 추가하기 위해 TouchID와 같은 시스템 기능을 사용하는 경우 ApplicationWillResignActive AppDelegate에서 호출되고, 당신이 말하면, 컨트롤러를 보안 루트 컨트롤러로 재설정하면 재 파용 및 PerformSegueWithidentifier (self.main_segue, sender : self) 발사하지 않을 것입니다!

이것은 뷰를 구성하기 위해 XIBS를 사용하여 스토리 보드에서 기존 방식으로 프로젝트를 병합했을 때 나에게 일어났다. 다시 전환하는 주된 이유는 내가 모달보기를 올바르게 올릴 수 없다는 사실 때문입니다. 내가 일반적으로하는 방식은 Uibutton의 대의원 메소드를 사용하여 특정 ViewController의 인스턴스를 구성하고 그 속성 중 일부를 설정하고 (대부분의 수입은 대의원이므로 모달 뷰 컨트롤러를 다시 기각 할 수 있음) 그것은 모달 방식으로. 새로운 스토리 보드 방식에서 이것은 아마도 Segue로 이루어 졌을 것입니다. Uistoryboardsegue 클래스를 확장하는 사용자 정의 클래스를 만들어 전환을 사용자 정의 할 수 있습니다. 나는이 방법이 간단한 방식과 비교하여 너무 많은 번거 로움을 발견했습니다.

이것이 어떻게 ViewController로드를 두 번하게 만들었습니까? 스토리 보드 프로젝트에서 XIB 프로젝트로 코드를 전송할 때 XIB (각 viewController마다 하나씩)를 만들었고 복사 스토리 보드에서 ViewController 객체. 이로 인해 VIW가 아니라 ViewController가있는 XIB가 생겼습니다. 의미가 ViewController에 ViewController를 넣었음을 의미합니다 (파일의 소유자도 ViewController의 인스턴스이기 때문에). 나는 당신의 경우 당신 이이 문제를 겪었다 고 생각하지 않지만 언젠가 누군가를 도울 수 있기를 바랍니다.

이 수정하려면보기 컨트롤러에서 뷰 컨트롤러에서 객체 섹션의 루트 레벨로 뷰를 움직입니다. 보기 컨트롤러와 내비게이션 항목 모두 삭제해야합니다. 빌드 및 실행하면 뷰 컨트롤러에 대한 하나의 할당 만 볼 수 있습니다. 이것은 파일 소유자입니다.

코드가 아직로드되지 않았을 때 코드가 뷰 속성에 액세스 한 경우 뷰 컨트롤러가 빈 뷰 만 생성하고 트리거 될 수 있습니다. view did load 우연히.

가장 일반적인 오류는 초기화 중 뷰 속성에 액세스하는 것입니다. XIB에 의해 호출되는 일부 부동산 액세서 (Setter) 일 수 있습니다.

일부 속성에 주석이 달리면 어떨까요? IBInspectable 확인해야합니다 isViewLoaded 보기에 약간의 값을 적용하기 전에.


-(void) setSomeProperty:(UIColor*) someColor
{
  _someColor = someColor;
  if(self.isViewLoaded) {
    // self.view causes view creation and invokes 'viewDidLoad' then the view is not ready yet.
    self.view.backgroundColor = someColor;
  }
}

-(void) viewDidLoad
{
  [super viewDidLoad]
  if(_someColor){
    self.view.backgroundColor = _someColor;
  }
}

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top