programing

iPhone의 세로에 있는 UISplitViewController에 마스터 대신 세부 VC가 표시됨

itmemos 2023. 6. 16. 21:26
반응형

iPhone의 세로에 있는 UISplitViewController에 마스터 대신 세부 VC가 표시됨

저는 iOS 7 이상을 대상으로 Xcode 6에서 유니버설 스토리보드를 사용하고 있습니다.다을구습다니했현을 했습니다.UISplitViewController이것은 현재 iOS 8을 실행하는 아이폰에서 기본적으로 지원되며, Xcode는 iOS 7용으로 자동으로 지원됩니다.는, controller를 볼 했을 때 됩니다. iOS 8의 Detail view controller는 iOS 8의 Detail view controller입니다. 뷰했습니다.하지만 iOS 8은 현재 GM이고 이것은 여전히 일어나고 있습니다.분할 보기 컨트롤러가 축소될 때(화면에 표시되는 보기 컨트롤러는 하나만) 분할 보기 컨트롤러가 표시될 때 마스터 보기 컨트롤러가 세부 정보가 아닌 것으로 표시되도록 설정하려면 어떻게 해야 합니까?

인터페이스 빌더에서 이 분할 뷰 컨트롤러를 만들었습니다.분할 보기 컨트롤러는 탭 모음 컨트롤러 내의 첫 번째 보기 컨트롤러입니다.마스터 및 세부 VC는 모두 테이블 뷰 컨트롤러가 내장된 탐색 컨트롤러입니다.

이런, 이것이 며칠 동안 저에게 두통을 일으켰고 어떻게 해야 할지 몰랐습니다.최악의 부분은 마스터 세부 템플릿으로 새로운 Xcode iOS 프로젝트를 만드는 것이 잘 작동했다는 것입니다.다행히도, 결국, 그 작은 사실이 제가 해결책을 찾은 방법이었습니다.

새로운 솔루션을 구현하는 것이 솔루션임을 시사하는 몇 가지 게시물이 있습니다.primaryViewControllerForCollapsingSplitViewController:에 있는 방법.UISplitViewControllerDelegate저는 그것을 시도했지만 소용이 없었습니다.것을 입니다. (이.) 애디이는마플보터스-테일템플릿에서다하는것니것입구는을요하하현위세심일을은운새흡로호해이말것모기하이동을든작처하는것럼이▁what디▁that▁implement▁thetake▁the▁(▁new▁seems▁does-(▁is애플det▁to▁to▁apple▁in▁masterail▁work▁template다요하세니▁a것▁breath▁deep▁all심▁one)▁of입을흡플이동▁this호위템모splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:위임 방법(다시 한 번UISplitViewControllerDelegate문서에 따르면 이 방법은 다음과 같습니다.

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

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

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 리가기것다니입는하대(a)).UINavigationController), 하는 (a), 그고리것가은그하리는기대것을다(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. 보기가 올바르지 않은 경우
    • 마스터 보기 컨트롤러 표시

맑음.

스위프트에서 수락된 답변입니다.이 하위 클래스를 만들어 스토리보드의 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
  }

}

마크 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
}

명확화

(Mark S가 말한 것은 약간 혼란스러웠습니다)

이 위임 방법을 다음과 같이 부릅니다.splitViewController: collapseSecondaryViewController: ontoPrimaryViewController:왜냐하면 그것이 그것이기 때문입니다.전화기를 가로에서 세로로 회전할 때와 같이 좀 더 컴팩트한 너비 크기로 변경할 경우 분할 보기 컨트롤러를 둘 중 하나로만 접어야 합니다.

이 함수는 세부 정보를 축소하고 마스터를 표시할지 여부를 결정하는 부울을 반환합니다.

그래서 우리의 경우에는 세부사항이 선택되었는지 여부를 기준으로 결정할 것입니다.우리의 세부사항이 선택되었는지 어떻게 알 수 있습니까?Apple의 Master-Detail 템플릿을 따르는 경우 Detail View 컨트롤러에 Detail 정보가 있는 선택적 변수가 있어야 하므로 0(.None)이면 아직 아무것도 선택되지 않았으며 사용자가 선택할 수 있도록 Master를 표시해야 합니다.

바로 그겁니다.

   #import <UIKit/UIKit.h>

    @interface SplitProductView : UISplitViewController<UISplitViewControllerDelegate>




    @end

.m:

#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

제 앱은 스위프트 2.x로 작성되어 잘 실행될 수 있었습니다.스위프트 3.0(XCode 컨버터 사용)으로 변환한 후 세로 모드에서 마스터가 아닌 디테일을 먼저 보여주기 시작합니다.문제는 함수 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
}

문서에서 딜러를 사용하여 다음 사항을 설명해야 합니다.UISplitViewController 상세 뷰를 "붕괴된 인터페이스"(즉, 이 경우 "세로 모드")에 통합하지 않습니다.Swift 4에서 구현할 대리자 메서드의 이름이 변경되었습니다.

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

상세 뷰 컨트롤러에 표시할 기본값이 없다면 스토리보드에서 스플릿뷰 컨트롤러와 상세 UIView 컨트롤러 사이의 기본값을 삭제하기만 하면 됩니다.이렇게 하면 항상 먼저 마스터 보기 컨트롤러로 이동합니다.

이로 인해 발생하는 부작용은 두 뷰를 가로로 보는 대신 마스터 뷰 컨트롤러에서 Show Detail Segue가 실행될 때까지 분할 뷰 컨트롤러에서 전체 크기로 한 뷰를 볼 수 있다는 것입니다.

제 생각에 당신은 이 문제를 좀 더 일반적으로 해결해야 할 것 같습니다.UISplitViewController를 하위 분류하고 포함된 보기 컨트롤러에 프로토콜을 구현할 수 있습니다.

class MasterShowingSplitViewController: UISplitViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

extension MasterShowingSplitViewController: UISplitViewControllerDelegate {
    func splitViewController(splitViewController: UISplitViewController,
                             collapseSecondaryViewController secondaryViewController: UIViewController,
                             ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
        guard let masterNavigationController = primaryViewController as? UINavigationController,
                  master = masterNavigationController.topViewController as? SplitViewControllerCollapseProtocol else {
            return true
        }
        return master.shouldShowMasterOnCollapse()

    }
}

protocol SplitViewControllerCollapseProtocol {
    func shouldShowMasterOnCollapse() -> Bool
}

UITableViewController에서의 구현 예:

extension SettingsTableViewController: SplitViewControllerCollapseProtocol {
    func shouldShowMasterOnCollapse() -> Bool {
        return tableView.indexPathForSelectedRow == nil
    }
}

도움이 되길 바랍니다.따라서 이 클래스를 재사용할 수 있으며 프로토콜만 구현하면 됩니다.

cs193p의 금요일 섹션을 찾지 못한 모든 사람들:

Swift 3.1.1에서는 UISplitViewController의 하위 클래스를 생성하고 대리 방법 중 하나를 구현하는 것이 매력적으로 작용했습니다.

class MainSplitViewController: UISplitViewController, UISplitViewControllerDelegate {

override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self
}

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

내 스토리보드

마스터에서 시작하려면 DetailView 컨트롤러를 스플릿뷰 컨트롤러에서 제거하기만 하면 됩니다.

UISplitViewController *splitViewController = (UISplitViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"SETTINGS"];
splitViewController.delegate = self;
[self.navigationController presentViewController:splitViewController animated:YES completion:nil];
if (IPHONE) {
    NSMutableArray * cntlrs = [splitViewController.viewControllers mutableCopy];
    [cntlrs removeLastObject];
    splitViewController.viewControllers = cntlrs;
}

이것은 iOS-11과 Swift 4에서 제게 효과가 있었습니다.

//Following code in application didFinishLaunching (inside Application Delegate)
guard let splitViewController = window?.rootViewController as? UISplitViewController,
            let masterNavVC = splitViewController.viewControllers.first as? UINavigationController,
            let masterVC = masterNavVC.topViewController as? MasterViewController
else { fatalError() }
splitViewController.delegate = masterVC

//Following code in MasterViewController class
extension MasterViewController:UISplitViewControllerDelegate {
    func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
        return true
    }
}

이 기능은 Swift의 새 버전에서 이름이 바뀌므로 이 코드는 Swift 4에서 작동합니다.

import UIKit

class GlobalSplitViewController: UISplitViewController, UISplitViewControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }

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

}

사마린 / C# 솔루션

public partial class MainSplitViewController : UISplitViewController
{
    public MainSplitViewController(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        Delegate = new MainSplitViewControllerDelegate();
    }
}

public class MainSplitViewControllerDelegate : UISplitViewControllerDelegate
{
    public override bool CollapseSecondViewController(UISplitViewController splitViewController, UIViewController secondaryViewController, UIViewController primaryViewController)
    {
        return true;
    }
}

설정만 하면 됩니다.preferredDisplayMode의 재산.UISplitViewController로..allVisible

class MySplitViewController: UISplitViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.preferredDisplayMode = .allVisible
    }

}

언급URL : https://stackoverflow.com/questions/25875618/uisplitviewcontroller-in-portrait-on-iphone-shows-detail-vc-instead-of-master

반응형