2013-11-21 1 views
13

그래서 컨트롤러 A를 루트 컨트롤러로 사용하여 UINavigationController가 있습니다.iOS 7은 일부 시간에만 사용자 지정 대화식 전환을 사용합니다.

컨트롤러 B를 맨 위에 놓을 때 나는 사용자 정의 애니메이션 전환 및 사용자 정의 대화식 전환을 사용하려고합니다. 이것은 잘 작동합니다. 내가 위에 컨트롤러 C를 밀어하려는 경우

, 내가 UINavigationController가 함께 제공되는 기본 푸시/팝 전환으로 폴백하려는. 하려면이

navigationController:interactionControllerForAnimationController: 

가 호출되지 기본 "왼쪽 가장자리에서 팬은"대화 형 전환이 작동하지 않습니다 나타 않을 것이다 다음, 당신이 전무를 반환하면 내가 그러나

navigationController:animationControllerForOperation:fromViewController:toViewController: 

을 위해 전무를 반환 일어난다.

기본 푸시/팝 애니메이션 컨트롤러 및 상호 작용 컨트롤러를 반환하는 방법이 있습니까? (id<UIViewControllerAnimatedTransitioning>id<UIViewControllerInteractiveTransitioning>의 구체적인 구현이 있습니까?)

또는 다른 방법이 있습니까?

답변

18

당신은 자기에있는 navigationController의 interactivePopGestureRecognizer 대리자를 설정 한 다음 -gestureRecognizerShouldBegin에서의 동작을 처리해야 :

입니다

, 당신은 내장 발사 팝 제스처,이 방법에서 YES 반환해야 할 때. 사용자 정의 제스처도 마찬가지입니다. 어떤 인식자를 처리해야하는지 파악해야합니다.

- (void)setup 
{ 
    self.interactiveGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTransitionGesture:)]; 
    self.interactiveGestureRecognizer.delegate = self; 
    [self.navigationController.view addGestureRecognizer:self.interactiveGestureRecognizer]; 

    self.navigationController.interactivePopGestureRecognizer.delegate = self; 
} 

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 
{ 
    // Don't handle gestures if navigation controller is still animating a transition 
    if ([self.navigationController.transitionCoordinator isAnimated]) 
     return NO; 

    if (self.navigationController.viewControllers.count < 2) 
     return NO; 

    UIViewController *fromVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-1]; 
    UIViewController *toVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-2]; 

    if ([fromVC isKindOfClass:[ViewControllerB class]] && [toVC isKindOfClass:[ViewControllerA class]]) 
    { 
     if (gestureRecognizer == self.interactiveGestureRecognizer) 
      return YES; 
    } 
    else if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) 
    { 
     return YES; 
    } 

    return NO; 
} 

시나리오에 따라 sample project을 확인할 수 있습니다. 뷰 컨트롤러 A와 B 사이의 전환은 맞춤형 B-> 팝 제스처가있는 맞춤 애니메이션입니다. 보기 컨트롤러 B와 C 사이의 전환은 기본적으로 네비게이션 컨트롤러의 팝업 제스처가 내장되어 있습니다.

희망이 도움이됩니다.

+0

애플의 DTS의 사람들에 따르면, 개인 interactivePopGestureRecognizer UINavigationController가 함께 제공되는 전용 API를 호출 일부의 위임에 수표의 번호를한다는 것을. 자신 만의 대표자를 구현한다고해서 모든 사례의 100 %가 보장되는 것은 아닙니다. – Ziconic

+0

@Ziconic 예의 경우? – Andy

0

사용자 지정 전환을 완료 한 후 (self.)navigationController.delegate에서 nil으로 설정하거나 이전 값으로 설정해보십시오.

10

예를 들어, prepareForSeque에 표시 할 때마다 위임자를 설정해야합니다. 사용자 정의 전환을 원할 경우 자체 전환으로 설정하십시오. 디폴트의 ​​트랜지션 (디폴트의 팝스 트랜지션 등)을 필요로하는 경우는 nil로 설정합니다.

+1

슬프게도 실제로는 정답이 아니며 Apple DTS 사람들이 권장하는 접근법입니다. 특히 우아한 것은 아닙니다. 기본적으로 2 개의 UINavigationControllerDelegate 객체가 필요합니다. 하나는 전환 콜백을 구현하는 객체이고 하나는 그렇지 않습니다 (또는 nil입니다). 기본 팝 전환을 얻으려면 콜백없이 델리게이트를 사용하거나 델리게이트를 nil로 설정하십시오. 사용자 정의 전환을 얻으려면 콜백이있는 대리자를 스왑 아웃하고 전환 완료 후 원래 대리자를 복원하십시오. – Ziconic

+0

여전히 권장되는 방법입니까? – ken

+0

@ken iOS 7 & 8에서 작동하므로 예라고 말합니다. – Jesse

0

을 자신의 제스처 인식기에 설정하고 대리자를 설정 한 다음 애니메이션 및 대화식 전환을 반환합니다. 대화 형 전환을 반환 할 때 대리자를 다시 설정 해제해야 나머지 모든 항목이 기본 전환을 계속 사용합니다.

나는 working example on github입니다. 각 전환이 유효한 해결 방법이지만, 다른 UINavigationControllerDelegate의 메소드를 구현하고이를 유지해야 할 경우, 당신은이 위임 개체가 할 수 있습니다 후

- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController 
{ 
    // Unset the delegate so that all other types of transitions (back, normal animated push not initiated by a gesture) get the default behavior. 
    self.navigationController.delegate = nil; 

    if (self.edgePanGestureRecognizer.state == UIGestureRecognizerStateBegan) { 
    self.percentDrivenInteractiveTransition = [UIPercentDrivenInteractiveTransition new]; 
    } else { 
    self.percentDrivenInteractiveTransition = nil; 
    } 

    return self.percentDrivenInteractiveTransition; 
} 
1

전에 대리자를 설정/Ziconic에 의해 제안 또는 놀이로 NSObject의 respondsToSelector:.네비게이션 위임에서는 구현할 수 :

- (BOOL)respondsToSelector:(SEL)aSelector 
{ 
    if (aSelector == @selector(navigationController:animationControllerForOperation:fromViewController:toViewController:) || 
     aSelector == @selector(navigationController:interactionControllerForAnimationController:)) { 

     return self.interactivePushTransitionEnabled; 
    } 

    return [super respondsToSelector:aSelector]; 
} 

은 그런 다음 필요에 따라 확인 interactivePushTransitionEnabled를 업데이트해야합니다. 귀하의 예제에서 컨트롤러 A가 표시되고있을 때만 속성을 YES으로 설정해야합니다.

할일이 하나 더 있습니다. 위임자가 구현 한 메서드를 재검토하도록 UINavigationController에 지시하십시오. 이것은 쉽게 다음과 같은 일을 수행 할 수 있습니다

navigationController.delegate = nil; 
navigationController.delegate = self; // or whatever object you use as the delegate 
관련 문제