2012-09-30 3 views
12

우리의 응용 프로그램을 스토리 보드로 변환하려고 시도하고 있으며 사용자 정의 컨테이너 컨트롤러를 다룰 때 unwind segues를 처리 할 때 버그가 있다고 생각합니다. 우리는 또 다른 하나를 표시하고 이것을 수행하기 위해 뷰 컨트롤러 봉쇄 API를 사용하는 뷰 컨트롤러가 있는데, 나는 IB의 세그 (segue)를 연결 한 다음 구현을위한 사용자 정의 클래스를 선택합니다. 완벽하게 작동사용자 정의보기 컨트롤러 포함을 사용할 때 unwind segues를 만들 수 없습니다.

-(void) perform { 
    UIViewController *container = [self sourceViewController]; 
    UIViewController *child = [self destinationViewController]; 
    [container addChildViewController:child]; 
    [container.view addSubview:child.view]; 
    child.view.center = container.view.center; 
    [UIView transitionWithView:container.view 
         duration:0.35 
         options:UIViewAnimationOptionCurveEaseInOut 
        animations:^{ 
         child.view.alpha = 1; 
        } completion:^(BOOL finished) { 
         [child didMoveToParentViewController:container]; 
        }]; 
} 

는, 그러나 나는 그것이 다시 용기 컨트롤러에 언 와인드 SEGUE을 수행 할 수 없습니다 다음 수행 방법은 다음과 같이 보입니다. fromViewController : withSender을 : 나는 viewControllerForUnwindSegueAction을 무시하고 올바른 값을 반환하는 것 있는지 확인하십시오

-(UIViewController *) viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender { 
    id default = [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender]; 
    NSAssert1(default == self, @"Expected the default view controller to be self but was %@", default); 
    return default; 
} 
나는 또한 그 canPerformUnwindSegueAction을 확인할 수 있습니다

는 : fromViewController : withSender 호출하고, 옳은 일을하고 있지만 반드시되고 있는지 나는 그것을 오버라이드 YES

-(BOOL) canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender { 
    return YES; 
} 

를 반환하는 나는 일이 기대하는 다음 단계는 segueForUnwindingToViewController입니다 : fromViewController : 식별자 : 호출 할, 그러나 그것이 결코. 대신 응용 프로그램이 NSInternalInconsistencyException과 충돌합니다.

2012-10-01 10:56:33.627 UnwindSegues[12770:c07] *** Assertion failure in -[UIStoryboardUnwindSegueTemplate _perform:], /SourceCache/UIKit_Sim/UIKit-2372/UIStoryboardUnwindSegueTemplate.m:78 
2012-10-01 10:56:33.628 UnwindSegues[12770:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not find a view controller to execute unwinding for <USCustomContainerViewController: 0x75949a0>' 
*** First throw call stack: 
(0x1c8e012 0x10cbe7e 0x1c8de78 0xb61f35 0x581711 0x45ab54 0x10df705 0x16920 0x168b8 0xd7671 0xd7bcf 0xd6d38 0x4633f 0x46552 0x243aa 0x15cf8 0x1be9df9 0x1be9ad0 0x1c03bf5 0x1c03962 0x1c34bb6 0x1c33f44 0x1c33e1b 0x1be87e3 0x1be8668 0x1365c 0x1e7d 0x1da5) 
libc++abi.dylib: terminate called throwing an exception 

누가보기 컨트롤러 포함 API와 결합 된 unwind segues를 성공적으로 사용 했습니까? 어떤 단계가 빠졌는지 알 수 있습니까? demo project to github을 업로드하여 가장 간단한 데모 프로젝트에서 문제점을 보여주었습니다.

+0

참조 : http://openradar.appspot.com/radar?id=2144402 –

답변

2

이것은 버그 인 것 같습니다. 구현 한대로 긴장을 풀 수도 있습니다.

내가 명시 적으로 IBAction를 방법에 제시된 뷰 컨트롤러를 기각되어 사용되는 해결 방법 :

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController 
             fromViewController:(UIViewController *)fromViewController 
               identifier:(NSString *)identifier 
{ 
    return [[UIStoryboardSegue alloc] initWithIdentifier:identifier 
               source:fromViewController 
              destination:toViewController]; 
} 

- (IBAction)unwind:(UIStoryboardSegue*)segue 
{ 
    UIViewController *vc = segue.sourceViewController; 
    [vc willMoveToParentViewController:nil]; 
    if ([vc respondsToSelector:@selector(beginAppearanceTransition:animated:)]) { 
     [vc beginAppearanceTransition:NO animated:YES]; // iOS 6 
    } 
    UIView *modal = vc.view; 
    UIView *target = [[segue destinationViewController] view]; 
    [UIView animateWithDuration:duration animations:^{ 
     modal.frame = CGRectMake(0, target.bounds.size.height, modal.frame.size.width, modal.frame.size.height); 
    } completion:^(BOOL finished) { 
     [modal removeFromSuperview]; 
     [vc removeFromParentViewController]; 
     if ([vc respondsToSelector:@selector(endAppearanceTransition)]) { 
      [vc endAppearanceTransition]; 
      } 
    }]; 
} 
5

당신의 예에서 문제가 더이 없다는 것이다. 입니다. 먼저, 컨테이너 뷰 컨트롤러를 다소 이상한 방식으로 생성합니다 (이 작업을 수행하는 데 도움이되는 새 IB "컨테이너보기"는 사용하지 않습니다). 둘째, 긴장을 풀 필요가 없습니다. 아무것도 올려 놓거나 아무것도 올려 놓지 않았습니다.

canPerformUnwindSegueAction이 실제로 상위 체인과상의되었으며, 적절한 위치에있는 경우 viewControllerForUnwindSegueActionsegueForUnwindingToViewController이 유효하다는 것을 보여주는 예제가 있습니다. 참조 :

https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/ch19p640presentedViewControllerStoryboard2

는 지금 또한 그것을 수정, GitHub의에 원본을 예 포크를 만든이 이러한 기능을 설명하도록 :

https://github.com/mattneub/UnwindSegues

은 정말 상황이되지 않습니다 여기서 "unwind"는 이 필요하고이지만 사용자 정의 컨테이너보기 컨트롤러가 관련되어있을 때 "unwind"가 사용되는 방법을 보여줍니다.

+0

링크는 https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/이어야합니다. ch19p640presentedViewControllerStoryboard2 편집을 시도했으나 편집이 6 자 미만이므로 허용하지 않습니다. – combinatorial

+0

수정 해 드리겠습니다. 충고 고맙습니다. – matt

+4

너무 나쁜 링크가 죽었습니다! 나는 해결책이 정말로 필요합니다 ... –

2

답변 전 간단한 간략한 설명 : iOS 6의 iPad 화면 하나에서 여러 컨테이너보기를 사용하고 코드에서 unwind segues를 호출 할 때 동일한 정확한 오류 메시지가 나타났습니다.처음에는 내 Segue가 Storyboards를 사용하여 Ctrl + 드래그하여 파일 소유자에서 Exit로 이동했기 때문에 문제가 될 수 있다고 생각했지만 각 VC에 Test Close 버튼을 넣었을 때와 동일한 결과가 나타났습니다. 그들은 긴장을 풀어줍니다. 나는 모달/푸쉬/팝업 세그가 아닌 임베드 세그먼트를 푸는 것을 시도하고 있다는 것을 깨달았습니다. 그래서 그것을하지 못하는 것이 합리적입니다. 결국, unwind segue가 성공하고 View Controller가 Container View에서 언로드되면 iOS 6은 그 자리에 화면에 빈 공간 만있을 것이라고 생각합니다. (제 경우에는 언로드하려고하는 컨테이너 뷰 뒤에있는 화면의 부동산을 다른 컨테이너 뷰로 가져 오지만, iOS는 두 가지가 연결되지 않았기 때문에이를 알지 못합니다.)

답변 : 이것은 메인 윈도우 또는 탐색/탭 컨트롤러의 일부로 모달, 푸시 또는 팝 오버 섹 그를 풀 수 있음을 깨닫게했습니다. 이것은 b/c iOS가 전체 화면을 책임지는 이전 VC가 있다는 것을 알고 있으며 다시 돌아가는 것이 안전합니다. 따라서 귀하의 경우, 아이 컨테이너보기가 아이 컨테이너보기를 닫는 것이 안전하도록 부모 컨테이너보기에 연결되어 있음을 iOS에 알리는 방법을 살펴 보겠습니다. 예를 들어, 하위 컨테이너보기를 표시 할 때 모달/푸시/팝 오버 세그를 수행하거나 사용자 정의 UINavigationController 클래스로 둘 다 래핑합니다 (사용자 정의 클래스 인 이유는 네비게이션 막대를 원하지 않는다고 가정합니다).

죄송 합니다만 정확한 코드를 제공 할 수는 없지만 지금까지 내가 가진 최고였습니다. 도움이되기를 바랍니다.

0

이 버그는 iOS9에서 수정 된 것 같습니다.

+0

이것은 주석이어야합니다. –

관련 문제