UISplitViewController ở chế độ dọc trên iPhone hiển thị chi tiết VC thay vì chính

180
Jordan H 2014-09-17 08:04.

Tôi đang sử dụng Bảng phân cảnh chung trong Xcode 6, nhắm mục tiêu iOS 7 trở lên. Tôi đã triển khai một ứng dụng hiện đã UISplitViewControllerđược hỗ trợ nguyên bản trên iPhone chạy iOS 8 và Xcode sẽ tự động hỗ trợ nó cho iOS 7. Nó hoạt động rất tốt, ngoại trừ khi bạn khởi chạy ứng dụng trên iPhone ở chế độ dọc chạy iOS 8, chế độ xem chi tiết của chế độ xem chia tách bộ điều khiển được hiển thị khi tôi mong đợi lần đầu tiên nhìn thấy bộ điều khiển chế độ xem chính. Tôi tin rằng đây là một lỗi với iOS 8 vì khi bạn chạy ứng dụng trên iOS 7, nó hiển thị chính xác bộ điều khiển chế độ xem chính. Nhưng iOS 8 hiện là GM và điều này vẫn đang xảy ra. Làm cách nào tôi có thể thiết lập nó để khi bộ điều khiển chế độ xem phân tách sẽ được thu gọn (chỉ hiển thị một bộ điều khiển chế độ xem trên màn hình), khi bộ điều khiển chế độ xem phân tách được hiển thị, nó hiển thị bộ điều khiển chế độ xem chính chứ không phải chi tiết?

Tôi đã tạo bộ điều khiển chế độ xem phân tách này trong Trình tạo giao diện. Bộ điều khiển chế độ xem phân tách là bộ điều khiển chế độ xem đầu tiên trong bộ điều khiển thanh tab. Cả VC chính và chi tiết đều là bộ điều khiển điều hướng với bộ điều khiển chế độ xem bảng được nhúng bên trong.

14 answers

241
Mark S 2014-09-18 07:12.

Ôi trời, điều này đã khiến tôi đau đầu trong vài ngày và không thể tìm ra cách để làm điều này. Phần tệ nhất là việc tạo một dự án iOS Xcode mới với mẫu chi tiết chính hoạt động tốt. May mắn thay, cuối cùng, sự thật nhỏ đó là cách tôi tìm ra giải pháp.

Có một số bài đăng tôi đã tìm thấy gợi ý rằng giải pháp là triển khai primaryViewControllerForCollapsingSplitViewController:phương pháp mới trên UISplitViewControllerDelegate. Tôi đã cố gắng mà không có kết quả. Những gì Apple làm trong mẫu tổng thể chi tiết dường như hoạt động là triển khai splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:phương pháp ủy quyền mới (hít thở sâu để nói tất cả điều này) (bật lại UISplitViewControllerDelegate). Theo tài liệu , phương pháp này:

Yêu cầu người ủy quyền điều chỉnh bộ điều khiển chế độ xem chính và kết hợp bộ điều khiển chế độ xem phụ vào giao diện thu gọn.

Hãy nhớ đọc phần thảo luận của phương pháp đó để biết thêm chi tiết cụ thể.

Cách mà Apple xử lý điều này là:

- (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;

    }
}

Việc triển khai này về cơ bản thực hiện những điều sau:

  1. Nếu secondaryViewControllerlà những gì chúng tôi đang mong đợi (a UINavigationController) và nó hiển thị những gì chúng tôi đang mong đợi (a DetailViewController- bộ điều khiển chế độ xem của bạn), nhưng không có mô hình ( detailItem), thì " Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded."
  2. Nếu không, hãy quay lại " NOđể cho phép bộ điều khiển chế độ xem phân tách thử và kết hợp nội dung của bộ điều khiển chế độ xem phụ vào giao diện thu gọn"

Kết quả như sau đối với iPhone ở chế độ dọc (bắt đầu ở chế độ dọc hoặc xoay sang dọc - hoặc chính xác hơn là loại kích thước nhỏ gọn):

  1. Nếu quan điểm của bạn là đúng
    • và có một mô hình, hiển thị bộ điều khiển chế độ xem chi tiết
    • nhưng không có mô hình, hãy hiển thị bộ điều khiển chế độ xem chính
  2. Nếu quan điểm của bạn không đúng
    • hiển thị bộ điều khiển chế độ xem chính

Trong như bùn.

61
Clifton Labrum 2015-05-01 14:10.

Đây là câu trả lời được chấp nhận trong Swift. Chỉ cần tạo lớp con này và gán nó cho splitViewController trong bảng phân cảnh của bạn.

//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
  }

}
21
NiñoScript 2015-12-17 05:33.

Phiên bản Swift của câu trả lời đúng Mark S '

Như được cung cấp bởi mẫu Master-Detail của Apple.

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
}

Làm rõ

(Những gì Mark S nói hơi khó hiểu)

Phương thức đại biểu này được gọi splitViewController: collapseSecondaryViewController: ontoPrimaryViewController:, bởi vì đó là những gì nó làm. Khi thay đổi kích thước chiều rộng nhỏ gọn hơn (ví dụ: khi xoay điện thoại từ ngang sang dọc), nó cần phải thu gọn bộ điều khiển chế độ xem chia nhỏ thành một trong số chúng.

Hàm này trả về một boolean để quyết định xem nó có nên thu gọn Chi tiết và hiển thị Bản chính hay không.

Vì vậy, trong trường hợp của chúng tôi, chúng tôi sẽ quyết định dựa trên việc có một chi tiết được chọn hay không. Làm thế nào để chúng tôi biết nếu chi tiết của chúng tôi được chọn? Nếu chúng ta làm theo mẫu Master-Detail của Apple, bộ điều khiển chế độ xem chi tiết phải có một biến tùy chọn có thông tin chi tiết, vì vậy nếu nó là nil (.None), chưa có gì được chọn và chúng ta nên hiển thị Master để người dùng có thể chọn một cái gì đó.

Đó là nó.

9
Gank 2014-12-17 22:47.
   #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
9
Tony 2016-07-03 17:48.

Ứng dụng của tôi được viết bằng Swift 2.x và có thể chạy tốt. Sau khi chuyển đổi nó thành Swift 3.0 (sử dụng trình chuyển đổi XCode), nó bắt đầu hiển thị chi tiết trước thay vì chính ở chế độ dọc. Vấn đề là tên của hàm splitViewController không được thay đổi để phù hợp với tên mới của UISplitViewControllerDelegate.

Sau khi thay đổi tên của chức năng đó theo cách thủ công, ứng dụng của tôi hiện có thể hoạt động bình thường:

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
}
9
oli 2017-07-01 05:28.

Từ tài liệu , bạn cần sử dụng một đại diện để yêu cầu UISplitViewController không kết hợp chế độ xem chi tiết vào "giao diện thu gọn" (tức là "Chế độ chân dung" trong trường hợp của bạn). Trong Swift 4, phương thức ủy nhiệm để triển khai cho điều đó đã được đổi tên:

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
    return true
}
7
Hao-Cher Hong 2015-02-17 17:35.

Nếu bạn không có giá trị mặc định để hiển thị trong bộ điều khiển chế độ xem chi tiết, bạn có thể chỉ cần xóa cấu trúc mặc định giữa SplitViewController và UIViewController chi tiết của bạn trong bảng câu chuyện. Điều này sẽ làm cho nó luôn đi vào Master View Controller đầu tiên.

Tác dụng phụ của việc này là thay vì nhìn thấy hai chế độ xem ở chế độ ngang, bạn sẽ thấy một chế độ xem ở kích thước đầy đủ trong SplitViewController cho đến khi kích hoạt Show Detail Segue trong bộ điều khiển chế độ xem chính.

4
Bartosz Kunat 2017-07-29 07:09.

Đối với tất cả những người không thể tìm thấy phần thứ sáu của cs193p:

Trong Swift 3.1.1, việc tạo một lớp con của UISplitViewController và triển khai một trong các phương thức ủy quyền của nó đã làm việc cho tôi như một sự quyến rũ:

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

Bảng phân cảnh của tôi

3
Noname 2016-04-18 12:05.

Theo tôi bạn nên giải quyết vấn đề này chung chung hơn. Bạn có thể phân lớp UISplitViewController và triển khai một giao thức trong bộ điều khiển chế độ xem được nhúng.

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
}

Triển khai ví dụ trong UITableViewController:

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

Hy vọng nó giúp. Vì vậy, bạn có thể sử dụng lại lớp này và chỉ cần triển khai một giao thức.

2
Borys Shcherbyna 2016-12-25 12:58.

Chỉ cần xóa DetailViewController khỏi bộ điều khiển SplitView khi bạn cần nó khởi động từ Master.

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;
}
2
Vishal Chaudhry 2017-12-31 08:28.

Điều này đã làm việc cho tôi trên iOS-11 và 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
    }
}
2
Saeed Ir 2018-11-09 23:15.

Hàm được đổi tên trong các phiên bản Swift mới, vì vậy mã này hoạt động trên 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
    }

}
0
Mark Moeykens 2017-10-31 06:20.

Giải pháp Xamarin / 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;
    }
}
0
Arash Etemad 2019-06-16 03:06.

Chỉ cần đặt thuộc preferredDisplayModetính của UISplitViewControllerthành.allVisible

class MySplitViewController: UISplitViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.preferredDisplayMode = .allVisible
    }

}

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Làm thế nào để xây dựng một quả địa cầu từ Scratch

Làm thế nào để xây dựng một quả địa cầu từ Scratch

Thời gian, sự kiên nhẫn, thời gian, sự cống hiến và thời gian chỉ là một vài trong số những thứ mà Peter Bellerby cần để thành lập và sau đó điều hành Bellerby & Co. Globemakers, một trong những công ty duy nhất trên Trái đất vẫn sản xuất các quả địa cầu bằng tay.

Năm giai đoạn đau buồn sau khi mất việc làm

Năm giai đoạn đau buồn sau khi mất việc làm

Đó là một ngày thứ Bảy, máy bay của tôi hạ cánh, và tôi đã sẵn sàng để thư giãn trong một kỳ nghỉ cuối tuần ngắn ngủi, khi một email đến trên điện thoại của tôi. Tôi đã mất việc.

Giữ an toàn cho danh tính của bạn với một cảnh báo đóng băng hoặc gian lận tín dụng

Giữ an toàn cho danh tính của bạn với một cảnh báo đóng băng hoặc gian lận tín dụng

Nếu bạn đã từng bị đánh cắp danh tính của mình, bạn biết đó là một trải nghiệm đáng sợ và căng thẳng. Một cách không phổ biến để ngăn chặn nó? Tín dụng bị đóng băng.

Buổi ra mắt phần 3 của The Good Place có một học sinh mới: Khán giả

Buổi ra mắt phần 3 của The Good Place có một học sinh mới: Khán giả

Eleanor (Kristen Bell) dường như đã tình nguyện cho chúng tôi làm vật tưởng nhớ. NBC's The Good Place là một chương trình thích thử thách tốt.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language