[ios] iPhone에서 세로로 표시된 UISplitViewController는 마스터 대신 세부 VC를 보여줍니다.

iOS 7 이상을 대상으로 Xcode 6에서 Universal Storyboard를 사용하고 있습니다. UISplitViewControlleriOS 8을 실행하는 iPhone에서 기본적으로 지원되는을 구현 했으며 Xcode는 iOS 7을 위해 자동으로 백 포트합니다 .iOS 8을 실행하는 세로로 iOS에서 앱을 시작하고 분할보기의 상세보기를 제외하고는 실제로 잘 작동합니다. 마스터 뷰 컨트롤러를 처음 볼 것으로 예상되면 컨트롤러가 표시됩니다. iOS 7에서 앱을 실행할 때 마스터 뷰 컨트롤러가 올바르게 표시되기 때문에 이것이 iOS 8의 버그라고 생각했습니다. 그러나 iOS 8은 이제 GM이며 여전히 발생하고 있습니다. 분할보기 컨트롤러가 축소 될 때 (화면에 하나의보기 컨트롤러 만 표시) 분할보기 컨트롤러가 표시 될 때 마스터보기 컨트롤러가 세부 정보가 아닌 것을 표시하도록 어떻게 설정할 수 있습니까?

Interface Builder에서이 분할 뷰 컨트롤러를 만들었습니다. 분할 뷰 컨트롤러는 탭 막대 컨트롤러 내의 첫 번째 뷰 컨트롤러입니다. 마스터 및 세부 VC는 모두 테이블 뷰 컨트롤러가 내장 된 내비게이션 컨트롤러입니다.



답변

오,이게 며칠 동안 두통을 일으켜서 어떻게해야할지 모르겠습니다. 최악의 부분은 master-detail 템플릿으로 새로운 Xcode iOS 프로젝트를 만드는 것이 잘 작동한다는 것입니다. 다행히도 그 작은 사실은 내가 해결책을 찾은 방법이었습니다.

해결책이에 새로운 primaryViewControllerForCollapsingSplitViewController:메소드 를 구현하는 것임을 제안하는 게시물이 있습니다 UISplitViewControllerDelegate. 나는 아무 소용이 없었습니다. Apple이 마스터-디테일 템플릿에서 작동하는 것처럼 보이는 것은 새로운 (심지어 숨을 쉬어) splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:델리게이트 메소드 (다시 UISplitViewControllerDelegate)를 구현하는 것입니다. docs 에 따르면 이 방법은 다음과 같습니다.

대리인에게 기본 뷰 컨트롤러를 조정하고 보조 뷰 컨트롤러를 축소 된 인터페이스에 통합하도록 요청합니다.

자세한 내용은 해당 방법의 토론 부분을 읽어보십시오.

Apple이 처리하는 방식은 다음과 같습니다.

- (BOOL)splitViewController:(UISplitViewController *)splitViewController
collapseSecondaryViewController:(UIViewController *)secondaryViewController
  ontoPrimaryViewController:(UIViewController *)primaryViewController {

    if ([secondaryViewController isKindOfClass:[UINavigationController class]]
        && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]]
        && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {

        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;

    } else {

        return NO;

    }
}

이 구현은 기본적으로 다음을 수행합니다.

  1. 경우 secondaryViewController우리는 (A를 기대하고 무엇 UINavigationController(A), 그리고 우리가 기대하는지 보여주는 것 DetailViewController– 뷰 컨트롤러), 그러나 (어떤 모델이 없습니다 detailItem“다음) Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
  2. 그렇지 않으면 ” NO분할보기 컨트롤러가 보조보기 컨트롤러의 내용을 축소 된 인터페이스에 통합하도록하려면”

결과는 세로로 iPhone에 대해 다음과 같습니다 (세로로 시작하거나 세로로 회전 또는보다 컴팩트 한 크기의 클래스).

  1. 보기가 올바른 경우
    • 모델이 있으며, 상세 뷰 컨트롤러를 보여줍니다
    • 모델이 없지만 마스터 뷰 컨트롤러를 표시
  2. 보기가 정확하지 않은 경우
    • 마스터 뷰 컨트롤러 표시

진흙처럼 맑아


답변

Swift에서 허용되는 답변은 다음과 같습니다. 이 서브 클래스를 만들어 스토리 보드의 splitViewController에 할당하십시오.

//GlobalSplitViewController.swift

import UIKit

class GlobalSplitViewController: UISplitViewController, UISplitViewControllerDelegate {

  override func viewDidLoad() {
    super.viewDidLoad()

    self.delegate = self
  }

  func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController!, ontoPrimaryViewController primaryViewController: UIViewController!) -> Bool{
    return true
  }

}


답변

Mark S의 정답의 신속한 버전

Apple의 Master-Detail 템플릿에서 제공합니다.

func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
    guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
    guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
    if topAsDetailController.detailItem == nil {
        // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return true
    }
    return false
}

설명

(마크 S가 말한 것은 약간 혼란 스럽다)

이 대리자 메서드는이라고 splitViewController: collapseSecondaryViewController: ontoPrimaryViewController:하는 것입니다. 더 작은 너비 크기로 변경하는 경우 (예 : 가로에서 세로로 전화를 회전 할 때) 분할보기 컨트롤러를 하나만 축소해야합니다.

이 함수는 세부 사항을 축소하고 마스터를 표시할지 여부를 결정하기 위해 부울을 리턴합니다.

우리의 경우에는 세부 사항이 선택되었는지 여부에 따라 결정됩니다. 세부 사항이 선택되었는지 어떻게 알 수 있습니까? Apple의 Master-Detail 템플릿을 따르는 경우, 상세도 컨트롤러에는 상세 정보를 갖는 선택적 변수가 있어야합니다. 따라서 nil (.None) 인 경우 아직 아무것도 선택하지 않았으며 사용자가 무언가를 선택할 수 있도록 마스터를 표시해야합니다.

그게 다야.


답변

로부터 문서 , 당신은 알려줄 수있는 대리자를 사용할 필요가 UISplitViewController 없습니다를 은 “붕괴 인터페이스”(즉, 귀하의 경우에는 “세로 모드”)로 상세보기를 통합 할 수 있습니다. Swift 4에서 구현할 델리게이트 메소드의 이름이 다음과 같이 변경되었습니다.

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
    return true
}


답변

   #import <UIKit/UIKit.h>

    @interface SplitProductView : UISplitViewController<UISplitViewControllerDelegate>




    @end

.미디엄:

#import "SplitProductView.h"
#import "PriceDetailTableView.h"

@interface SplitProductView ()

@end

@implementation SplitProductView

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.delegate = self;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/
- (BOOL)splitViewController:(UISplitViewController *)splitViewController
collapseSecondaryViewController:(UIViewController *)secondaryViewController
  ontoPrimaryViewController:(UIViewController *)primaryViewController {

    if ([secondaryViewController isKindOfClass:[UINavigationController class]]
        && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[PriceDetailTableView class]]

        //&& ([(PriceDetailTableView *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)

        ) {

        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;

    } else {

        return NO;

    }
}
@end


답변

내 응용 프로그램은 Swift 2.x로 작성되었으며 제대로 실행될 수 있습니다. Xcode 변환기를 사용하여 Swift 3.0으로 변환 한 후에는 세로 모드에서 마스터 대신 세부 정보를 먼저 표시하기 시작합니다. 문제는 splitViewController 함수의 이름이 새로운 UISplitViewControllerDelegate와 일치하도록 변경되지 않는다는 것입니다.

해당 기능의 이름을 수동으로 변경하면 내 앱이 올바르게 작동 할 수 있습니다.

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
    guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
    guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
    if topAsDetailController.game == nil {
        // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return true
    }
    return false
}


답변

디테일 뷰 컨트롤러에 표시 할 기본값이없는 경우 스토리 보드에서 SplitViewController와 디테일 UIViewController 사이의 기본 세그를 삭제하기 만하면됩니다. 이렇게하면 항상 마스터 뷰 컨트롤러로 먼저 이동합니다.

이것의 부작용은 가로로 두 개의 뷰를 보는 대신 마스터 뷰 컨트롤러에서 Show Detail Segue가 시작될 때까지 SplitViewController에서 한 개의 뷰를 전체 크기로 볼 수 있다는 것입니다.