Segue를 사용하여 UINavigationController의 화면 전환 애니메이션 변경

17336 단어 StoryboardiOS
Storyboard를 사용하면 화면 전환에 Segue를 사용할 수 있습니다.
NavigationController를 사용한 전환에서 사용하는 segue는 내장 push를 사용하지만,
Custom Segue를 정의하고 화면 전환의 애니메이션을 고유한 것으로 변경하는 경우 몇 가지 고려해야 할 수도 있습니다.
  • 전환 된 화면에서 되돌아 가는 Segue (unwind segue)도 정의하거나 Segue에 의존하지 않고 뒤로 버튼을 누른 액션 메소드에 자체적으로 뒤로 애니메이션을 작성할지
  • NavigationBar의 뒤로 버튼을 별도 준비
  • UINavigationController 로 천이하고 있는 경우, 몇개의 unwind segue 의 메소드는 컨테이너 ViewController 가 되고 있는 UINavigationController 의 것이 불린다

  • 여기에서는 unwind segue를 준비하여 화면 전환해 보겠습니다.

    Custom Segue 만들기



    Segue/Unwind segue 모두 대응하는 Custom Segue를 작성합니다. Apple sample code를 참고했습니다.

    UnwindSegue

    NavigateFlipSegue.h
    #import <UIKit/UIKit.h>
    
    @interface NavigateFlipSegue : UIStoryboardSegue
    
    @property (nonatomic) BOOL unwind;  // unwind segueのインスタンスを作成時に設定するflag
    
    @end
    

    NavigateFlipSegue.m
    #import "NavigateFlipSegue.h"
    
    @implementation NavigateFlipSegue
    
    - (void)perform
    {
        UIViewController *sourceViewController = self.sourceViewController;
        UIViewController *destinationViewController = self.destinationViewController;
        UINavigationController *navigationController = sourceViewController.navigationController;
    
        if (self.unwind) {  // Unwind segueの場合は、右からflipするアニメーション
            [UIView transitionWithView:navigationController.view duration:0.3f options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
                [navigationController popToRootViewControllerAnimated:NO];
            } completion:nil];
        } else {    // segueの場合は、左からflipするアニメーション
            [UIView transitionWithView:navigationController.view duration:0.3f options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
                [navigationController pushViewController:destinationViewController animated:NO];
            } completion:nil];
        }
    }
    

    Custom NavigationController 만들기



    NavigationController 기반 화면 전환의 경우 unwind segue에 대한 Custom segue를 반환하는 메서드는 NavigationController의 메서드를 호출하므로 childViewController에 처리를 위임합니다.
    구현적으로는, 위양용의 Protocol 를 정의해, 돌려주는 ChildViewController 에 적용합니다.
    unwind segue용 메소드가 불려 가면, 위양용 Protocol가 적용되고 있는 ChildViewController의 메소드를 호출 segue가 생성되어 오히려 오면, 그 segue를 돌려주도록(듯이) 합니다.
    그런 다음 스토리 보드에 배치 한 UINavigationController는이 Custom NavigationController를 사용하도록 변경합니다.



    MyNavigationController.h
    #import <UIKit/UIKit.h>
    
    // ChildViewControllerで実装
    @protocol MyNavigationControllerDelegate <NSObject>
    
    /*!
        @method segueInNavigationControllerForUnwindingToViewController:fromViewController:identifier:
        @abstract NavigationControllerによる遷移でunwindする場合、custom segueを使いたい場合に実装する
        @discussion 戻る側のViewControllerでunwind segueの実装してNavigationControllerでは何もしない(委譲)
        @return Custom Segueを生成して返すように実装
     */
    - (UIStoryboardSegue *)segueInNavigationControllerForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier;
    
    @end
    
    @interface MyNavigationController : UINavigationController
    
    @end
    

    MyNavigationController.m
    #import "MyNavigationController.h"
    
    @interface MyNavigationController ()
    
    @end
    
    @implementation MyNavigationController
    
    - (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier
    {
        // MARK: 実際の戻り先ChildViewControllerに処理を任せる
        if ([toViewController conformsToProtocol:@protocol(MyNavigationControllerDelegate)]) {
            id <MyNavigationControllerDelegate> destinationViewController = (id <MyNavigationControllerDelegate>)toViewController;
            UIStoryboardSegue *segue = [destinationViewController segueInNavigationControllerForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
            if (segue) {
                return segue;
            }
        }
    
        return [super segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
    }
    
    @end
    

    Unwind segue의 정의 및 위양용 프로토콜 메소드의 구현



    반환되는 ChildViewController에서 unwind segue를 정의하고 프로토콜 메서드를 구현합니다.

    MasterViewController.m
    #import "MasterViewController.h"
    
    #import "DetailViewController.h"
    #import "MyNavigationController.h"
    #import "NavigateFlipSegue.h"
    
    @interface MasterViewController () <MyNavigationControllerDelegate> // 委譲用プロトコルの適用
    - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
    @end
    
    @implementation MasterViewController
    
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        if ([[segue identifier] isEqualToString:@"showDetail"]) {
            NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
            NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
            [[segue destinationViewController] setDetailItem:object];
        }
    }
    
    // unwind segueの定義
    - (IBAction)exitToMasterView:(UIStoryboardSegue *)segue
    {
        // XXX: No-op. unwind segue.
    }
    
    #pragma mark - MyNavigationControllerDelegate
    
    // 委譲用プロトコルメソッドの実装
    - (UIStoryboardSegue *)segueInNavigationControllerForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier
    {
        if ([identifier isEqualToString:@"existFromDetail"]) {  // custom segueの生成
            NavigateFlipSegue *segue = [[NavigateFlipSegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController];
            segue.unwind = YES; // unwind segueなのでセット
            return segue;
        }
        return nil;
    }
    

    스토리 보드에서 segue 설정



    우선, Segue의 Style은 custom으로 하고, 작성한 Custom segue 클래스를 사용하도록(듯이) 설정합니다.



    그런 다음 뒤로 버튼을 추가하고 unwind segue를 끈다.




    참고


  • UnwindSegue
  • CustomUnwindSegue
  • 샘플 코드
  • 좋은 웹페이지 즐겨찾기