{"id":6936,"date":"2025-12-10T19:52:15","date_gmt":"2025-12-10T11:52:15","guid":{"rendered":"https:\/\/t.n-years.com\/?p=6936"},"modified":"2025-12-10T19:52:15","modified_gmt":"2025-12-10T11:52:15","slug":"%e3%80%90ipad-%e9%80%82%e9%85%8d%e3%80%91%e4%be%a7%e8%be%b9%e6%a0%8f-%e9%a1%b6%e9%83%a8%e5%af%bc%e8%88%aa%e5%ae%9e%e7%8e%b0%e5%a4%9a%e5%b1%82%e7%ba%a7","status":"publish","type":"post","link":"https:\/\/t.n-years.com\/?p=6936","title":{"rendered":"\u3010iPad \u9002\u914d\u3011\u4fa7\u8fb9\u680f + \u9876\u90e8\u5bfc\u822a\u5b9e\u73b0\u591a\u5c42\u7ea7"},"content":{"rendered":"<p>\u5728 iPad \u4e0a\u66ff\u4ee3\u201c\u5e95\u90e8 TabBar \u4e3b\u5bfc\u822a\u201d\u3001\u5b9e\u73b0\u300c\u4fa7\u8fb9\u680f + \u9876\u90e8\u5bfc\u822a\u300d\u7684\u591a\u5c42\u7ea7\u9ad8\u6548\u5bfc\u822a\uff0c\u6838\u5fc3\u662f\u5229\u7528 iOS \u539f\u751f\u7684 <code>UISplitViewController<\/code>\uff08\u62c6\u5206\u89c6\u56fe\u63a7\u5236\u5668\uff09\u7ed3\u5408 <code>UINavigationController<\/code>\uff0c\u9002\u914d\u5927\u5c4f\u4ea4\u4e92\u903b\u8f91\u7684\u540c\u65f6\u517c\u987e\u5c0f\u5c3a\u5bf8\/\u7ad6\u5c4f\u7684\u6298\u53e0\u573a\u666f\u3002\u4ee5\u4e0b\u662f<strong>\u5177\u4f53\u5b9e\u73b0\u6b65\u9aa4 + \u5173\u952e\u4ee3\u7801 + \u4f53\u9a8c\u4f18\u5316<\/strong>\uff0c\u4ee5 Swift \u4e3a\u4f8b\uff1a<\/p>\n<h3>\u4e00\u3001\u6838\u5fc3\u601d\u8def<\/h3>\n<p>iPad \u6a2a\u5c4f\u65f6\uff1a\u5de6\u4fa7\u5c55\u793a\u300c\u4fa7\u8fb9\u680f\uff08\u83dc\u5355\uff09\u300d\uff0c\u53f3\u4fa7\u5c55\u793a\u300c\u9876\u90e8\u5bfc\u822a + \u5185\u5bb9\u533a\u300d\uff0c\u4fa7\u8fb9\u680f\u53ef\u6536\u8d77\/\u5c55\u5f00\uff1b<br \/>\niPad \u7ad6\u5c4f\/\u5206\u5c4f\u5c0f\u5c3a\u5bf8\u65f6\uff1a\u4fa7\u8fb9\u680f\u81ea\u52a8\u6298\u53e0\u4e3a\u300c\u9876\u90e8\u5bfc\u822a\u7684\u4e0b\u62c9\u83dc\u5355\u300d\u6216\u300c\u5168\u5c4f\u65f6\u7684\u4fa7\u8fb9\u62bd\u5c49\u300d\uff0c\u4fdd\u6301\u64cd\u4f5c\u4e00\u81f4\u6027\uff1b<br \/>\n\u591a\u5c42\u7ea7\u7ba1\u7406\uff1a\u4fa7\u8fb9\u680f\u63a7\u5236\u4e00\u7ea7\u5206\u7c7b\uff0c\u9876\u90e8\u5bfc\u822a\u63a7\u5236\u4e8c\u7ea7\/\u4e09\u7ea7\u529f\u80fd\uff0c\u5185\u5bb9\u533a\u5c55\u793a\u5177\u4f53\u9875\u9762\u3002<\/p>\n<h3>\u4e8c\u3001\u5177\u4f53\u5b9e\u73b0\u6b65\u9aa4<\/h3>\n<h4>1. \u57fa\u7840\u67b6\u6784\u642d\u5efa\uff08SplitViewController + NavigationController\uff09<\/h4>\n<p><code>UISplitViewController<\/code> \u662f iPad \u4fa7\u8fb9\u680f\u7684\u6838\u5fc3\u7ec4\u4ef6\uff0c\u9ed8\u8ba4\u5206\u4e3a\u300c\u4e3b\u89c6\u56fe\uff08Primary\uff09\u300d\u548c\u300c\u8be6\u60c5\u89c6\u56fe\uff08Secondary\uff09\u300d\uff0c\u4e3b\u89c6\u56fe\u653e\u4fa7\u8fb9\u680f\uff0c\u8be6\u60c5\u89c6\u56fe\u5d4c\u5957 <code>UINavigationController<\/code> \u627f\u8f7d\u9876\u90e8\u5bfc\u822a + \u5185\u5bb9\u3002<\/p>\n<pre><code class=\"language-swift\">import UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    var window: UIWindow?\n\n    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool {\n        \/\/ 1. \u521b\u5efa\u4fa7\u8fb9\u680f\uff08\u4e3b\u89c6\u56fe\uff09\n        let sidebarVC = SidebarViewController()\n        let sidebarNav = UINavigationController(rootViewController: sidebarVC)\n\n        \/\/ 2. \u521b\u5efa\u8be6\u60c5\u533a\uff08\u9876\u90e8\u5bfc\u822a + \u521d\u59cb\u5185\u5bb9\uff09\n        let homeVC = HomeViewController()\n        let detailNav = UINavigationController(rootViewController: homeVC)\n\n        \/\/ 3. \u521d\u59cb\u5316 SplitViewController\n        let splitVC = UISplitViewController(style: .doubleColumn)\n        splitVC.preferredStyle = .sidebar \/\/ \u5f3a\u5236\u4fa7\u8fb9\u680f\u6837\u5f0f\uff08iPad \u4f18\u5148\uff09\n        splitVC.setViewController(sidebarNav, for: .primary)\n        splitVC.setViewController(detailNav, for: .secondary)\n\n        \/\/ 4. \u914d\u7f6e SplitView \u884c\u4e3a\n        splitVC.preferredSplitBehavior = .tile \/\/ \u6a2a\u5c4f\u65f6\u4fa7\u8fb9\u680f\u56fa\u5b9a\uff0c\u4e0d\u81ea\u52a8\u9690\u85cf\n        splitVC.presentsWithGesture = true \/\/ \u652f\u6301\u6ed1\u52a8\u547c\u51fa\/\u6536\u8d77\u4fa7\u8fb9\u680f\n        splitVC.delegate = self \/\/ \u76d1\u542c\u6298\u53e0\/\u5c55\u5f00\u72b6\u6001\n\n        \/\/ 5. \u8bbe\u7f6e\u6839\u89c6\u56fe\n        window = UIWindow(frame: UIScreen.main.bounds)\n        window?.rootViewController = splitVC\n        window?.makeKeyAndVisible()\n\n        return true\n    }\n}\n\n\/\/ MARK: - SplitViewController \u4ee3\u7406\uff08\u5904\u7406\u6298\u53e0\/\u5c55\u5f00\uff09\nextension AppDelegate: UISplitViewControllerDelegate {\n    func splitViewController(_ svc: UISplitViewController, topColumnForCollapsingToProposedTopColumn proposedTopColumn: UISplitViewController.Column) -&gt; UISplitViewController.Column {\n        \/\/ \u6298\u53e0\u65f6\u4f18\u5148\u4fdd\u7559\u8be6\u60c5\u533a\uff08\u9876\u90e8\u5bfc\u822a\uff09\n        return .secondary\n    }\n}<\/code><\/pre>\n<h4>2. \u5b9e\u73b0\u4fa7\u8fb9\u680f\uff08SidebarViewController\uff09<\/h4>\n<p>\u4fa7\u8fb9\u680f\u7528 <code>UITableView<\/code> \u5b9e\u73b0\u4e00\u7ea7\u83dc\u5355\uff0c\u9009\u4e2d\u9879\u65f6\u89e6\u53d1\u8be6\u60c5\u533a\u7684\u9875\u9762\u8df3\u8f6c\uff0c\u9002\u914d iPad \u89e6\u63a7\u5c3a\u5bf8\uff08\u884c\u9ad8\u3001\u95f4\u8ddd\u653e\u5927\uff09\u3002<\/p>\n<pre><code class=\"language-swift\">class SidebarViewController: UITableViewController {\n    \/\/ \u4e00\u7ea7\u83dc\u5355\u6570\u636e\n    let menuItems = [\n        (&quot;\u9996\u9875&quot;, UIImage(systemName: &quot;house&quot;)),\n        (&quot;\u6587\u6863&quot;, UIImage(systemName: &quot;doc.text&quot;)),\n        (&quot;\u8bbe\u7f6e&quot;, UIImage(systemName: &quot;gear&quot;)),\n        (&quot;\u5173\u4e8e&quot;, UIImage(systemName: &quot;info.circle&quot;))\n    ]\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \/\/ \u9002\u914d iPad \u6837\u5f0f\n        tableView.rowHeight = 60 \/\/ \u884c\u9ad8\u6bd4\u624b\u673a\u7aef\u5927\uff08\u624b\u673a\u7aef\u901a\u5e3844-50pt\uff09\n        tableView.separatorInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)\n        tableView.backgroundColor = .systemBackground\n\n        \/\/ \u9690\u85cf\u4fa7\u8fb9\u680f\u81ea\u8eab\u7684\u5bfc\u822a\u680f\uff08\u4ec5\u4fdd\u7559\u8be6\u60c5\u533a\u9876\u90e8\u5bfc\u822a\uff09\n        navigationController?.setNavigationBarHidden(true, animated: false)\n    }\n\n    \/\/ MARK: - TableView \u4ee3\u7406\n    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {\n        return menuItems.count\n    }\n\n    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {\n        let cell = UITableViewCell(style: .default, reuseIdentifier: &quot;SidebarCell&quot;)\n        let (title, icon) = menuItems[indexPath.row]\n        cell.textLabel?.text = title\n        cell.textLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium) \/\/ \u5b57\u53f7\u653e\u5927\n        cell.imageView?.image = icon\n        cell.imageView?.tintColor = .systemBlue\n        cell.accessoryType = .disclosureIndicator \/\/ \u6307\u793a\u53ef\u8df3\u8f6c\n        \/\/ \u6700\u5c0f\u70b9\u51fb\u533a\u57df\u786e\u4fdd 44pt\u00d744pt\uff08iPad \u89e6\u63a7\u66f4\u53cb\u597d\uff09\n        cell.contentView.layoutMargins = UIEdgeInsets(top: 10, left: 16, bottom: 10, right: 16)\n        return cell\n    }\n\n    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {\n        tableView.deselectRow(at: indexPath, animated: true)\n\n        \/\/ \u83b7\u53d6 SplitView \u7684\u8be6\u60c5\u533a\u5bfc\u822a\u63a7\u5236\u5668\n        guard let splitVC = self.splitViewController,\n              let detailNav = splitVC.viewController(for: .secondary) as? UINavigationController else {\n            return\n        }\n\n        \/\/ \u6839\u636e\u9009\u4e2d\u9879\u8df3\u8f6c\u5bf9\u5e94\u9875\u9762\uff08\u4e8c\u7ea7\u5185\u5bb9\uff09\n        switch indexPath.row {\n        case 0:\n            detailNav.setViewControllers([HomeViewController()], animated: true)\n        case 1:\n            detailNav.setViewControllers([DocumentViewController()], animated: true)\n        case 2:\n            detailNav.setViewControllers([SettingViewController()], animated: true)\n        case 3:\n            detailNav.setViewControllers([AboutViewController()], animated: true)\n        default:\n            break\n        }\n    }\n}<\/code><\/pre>\n<h4>3. \u8be6\u60c5\u533a\u9876\u90e8\u5bfc\u822a\uff08UINavigationController\uff09<\/h4>\n<p>\u8be6\u60c5\u533a\u7684\u6bcf\u4e2a\u9875\u9762\u5d4c\u5957\u5728 <code>UINavigationController<\/code> \u4e2d\uff0c\u5b9e\u73b0\u4e8c\u7ea7\/\u4e09\u7ea7\u5bfc\u822a\uff0c\u540c\u65f6\u9002\u914d iPad \u9876\u90e8\u5bfc\u822a\u7684\u6837\u5f0f\uff1a<\/p>\n<pre><code class=\"language-swift\">class HomeViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        view.backgroundColor = .white\n\n        \/\/ 1. \u914d\u7f6e\u9876\u90e8\u5bfc\u822a\u680f\uff08iPad \u6837\u5f0f\uff09\n        navigationItem.title = &quot;\u9996\u9875&quot;\n        navigationController?.navigationBar.prefersLargeTitles = true \/\/ \u5927\u6807\u9898\uff08iPad \u66f4\u9192\u76ee\uff09\n        navigationItem.largeTitleDisplayMode = .always\n\n        \/\/ 2. \u6dfb\u52a0\u4e8c\u7ea7\u64cd\u4f5c\u6309\u94ae\uff08\u9876\u90e8\u5bfc\u822a\u53f3\u4fa7\uff09\n        let addBtn = UIBarButtonItem(\n            barButtonSystemItem: .add,\n            target: self,\n            action: #selector(addAction)\n        )\n        let filterBtn = UIBarButtonItem(\n            image: UIImage(systemName: &quot;slider.horizontal.3&quot;),\n            style: .plain,\n            target: self,\n            action: #selector(filterAction)\n        )\n        navigationItem.rightBarButtonItems = [addBtn, filterBtn]\n\n        \/\/ 3. \u9002\u914d iPad \u5185\u5bb9\u533a\u5e03\u5c40\uff08\u793a\u4f8b\uff1a\u6dfb\u52a0\u4e00\u4e2a\u5217\u8868\uff09\n        let listView = UITableView(frame: view.bounds)\n        listView.rowHeight = 60\n        listView.dataSource = self\n        view.addSubview(listView)\n        listView.translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            listView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),\n            listView.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n            listView.trailingAnchor.constraint(equalTo: view.trailingAnchor),\n            listView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)\n        ])\n    }\n\n    @objc func addAction() {\n        \/\/ \u8df3\u8f6c\u5230\u4e09\u7ea7\u9875\u9762\uff08\u793a\u4f8b\uff1a\u65b0\u5efa\u6587\u6863\uff09\n        let createVC = CreateDocumentViewController()\n        navigationController?.pushViewController(createVC, animated: true)\n    }\n\n    @objc func filterAction() {\n        \/\/ \u9876\u90e8\u5bfc\u822a\u7684\u4e8c\u7ea7\u64cd\u4f5c\uff08\u793a\u4f8b\uff1a\u7b5b\u9009\uff09\n        let filterVC = FilterViewController()\n        filterVC.modalPresentationStyle = .popover \/\/ iPad \u5f39\u51fa\u5f0f\u5f39\u7a97\uff08\u4e0d\u5360\u6ee1\u5c4f\uff09\n        filterVC.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItems?[1]\n        present(filterVC, animated: true)\n    }\n}\n\n\/\/ MARK: - \u5185\u5bb9\u533a\u5217\u8868\u9002\u914d\nextension HomeViewController: UITableViewDataSource {\n    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {\n        return 20\n    }\n\n    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {\n        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: &quot;HomeCell&quot;)\n        cell.textLabel?.text = &quot;\u5185\u5bb9\u9879 \\(indexPath.row + 1)&quot;\n        cell.detailTextLabel?.text = &quot;iPad \u9002\u914d\u7684\u8be6\u60c5\u63cf\u8ff0&quot;\n        cell.detailTextLabel?.font = UIFont.systemFont(ofSize: 14)\n        return cell\n    }\n}<\/code><\/pre>\n<h4>4. \u9002\u914d\u6298\u53e0\/\u5206\u5c4f\u573a\u666f\uff08\u5173\u952e\u4f18\u5316\uff09<\/h4>\n<p>\u5f53 iPad \u7ad6\u5c4f\u3001\u5206\u5c4f\u5c0f\u5c3a\u5bf8\u65f6\uff0c\u4fa7\u8fb9\u680f\u4f1a\u81ea\u52a8\u6298\u53e0\uff0c\u9700\u5728\u8be6\u60c5\u533a\u9876\u90e8\u5bfc\u822a\u6dfb\u52a0\u300c\u4fa7\u8fb9\u680f\u547c\u51fa\u6309\u94ae\u300d\uff0c\u4fdd\u8bc1\u64cd\u4f5c\u5165\u53e3\u4e0d\u4e22\u5931\uff1a<\/p>\n<pre><code class=\"language-swift\">\/\/ \u5728\u8be6\u60c5\u533a\u7684\u57fa\u7c7b ViewController \u4e2d\u7edf\u4e00\u5904\u7406\nclass BaseDetailViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \/\/ \u6dfb\u52a0\u4fa7\u8fb9\u680f\u547c\u51fa\u6309\u94ae\uff08\u4ec5\u6298\u53e0\u65f6\u663e\u793a\uff09\n        let sidebarBtn = UIBarButtonItem(\n            image: UIImage(systemName: &quot;sidebar.left&quot;),\n            style: .plain,\n            target: self,\n            action: #selector(toggleSidebar)\n        )\n        navigationItem.leftBarButtonItem = sidebarBtn\n    }\n\n    @objc func toggleSidebar() {\n        \/\/ \u89e6\u53d1 SplitView \u5c55\u5f00\/\u6536\u8d77\u4fa7\u8fb9\u680f\n        splitViewController?.show(.primary)\n    }\n\n    \/\/ \u76d1\u542c SplitView \u6298\u53e0\u72b6\u6001\uff0c\u52a8\u6001\u663e\u793a\/\u9690\u85cf\u547c\u51fa\u6309\u94ae\n    override func viewWillAppear(_ animated: Bool) {\n        super.viewWillAppear(animated)\n        guard let splitVC = splitViewController else { return }\n        \/\/ \u6298\u53e0\u72b6\u6001\uff08\u7ad6\u5c4f\/\u5c0f\u5c3a\u5bf8\uff09\u663e\u793a\u547c\u51fa\u6309\u94ae\uff0c\u5c55\u5f00\u72b6\u6001\u9690\u85cf\n        navigationItem.leftBarButtonItem?.isHidden = !splitVC.isCollapsed\n    }\n}\n\n\/\/ \u8ba9\u6240\u6709\u8be6\u60c5\u9875\u9762\u7ee7\u627f BaseDetailViewController\nclass HomeViewController: BaseDetailViewController { \/* ... *\/ }\nclass DocumentViewController: BaseDetailViewController { \/* ... *\/ }<\/code><\/pre>\n<h3>\u4e09\u3001\u4f53\u9a8c\u4f18\u5316\u8981\u70b9\uff08iPad \u4e13\u5c5e\uff09<\/h3>\n<ol>\n<li>\n<p><strong>\u63a7\u4ef6\u5c3a\u5bf8\u9002\u914d<\/strong><\/p>\n<ul>\n<li>\u4fa7\u8fb9\u680f\u884c\u9ad8 \u2265 60pt\uff0c\u9876\u90e8\u5bfc\u822a\u6309\u94ae\u70b9\u51fb\u533a\u57df \u2265 44pt\u00d744pt\uff1b<\/li>\n<li>\u5185\u5bb9\u533a\u6587\u672c\u5b57\u53f7\u6bd4\u624b\u673a\u7aef\u5927 2-4pt\uff08\u5982\u6b63\u6587 16pt\uff0c\u526f\u6807\u9898 14pt\uff09\uff1b<\/li>\n<li>\u5f39\u7a97\u4f18\u5148\u4f7f\u7528 <code>UIPopoverPresentationController<\/code>\uff08iPad \u5f39\u51fa\u5f0f\uff09\uff0c\u800c\u975e\u5360\u6ee1\u5c4f\u7684 <code>modal<\/code>\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u6a2a\u7ad6\u5c4f\u5207\u6362\u9002\u914d<\/strong><\/p>\n<ul>\n<li>\u91cd\u5199 <code>viewWillTransition(to:with:)<\/code> \u76d1\u542c\u5c4f\u5e55\u65cb\u8f6c\uff0c\u8c03\u6574 SplitView \u5e03\u5c40\uff1a\n<pre><code class=\"language-swift\">override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n coordinator.animate { _ in\n     self.tableView.reloadData() \/\/ \u5237\u65b0\u5185\u5bb9\u533a\u5e03\u5c40\n     self.navigationItem.leftBarButtonItem?.isHidden = !self.splitViewController?.isCollapsed ?? false\n }\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u53f0\u524d\u8c03\u5ea6\uff08Stage Manager\uff09\u9002\u914d<\/strong><\/p>\n<ul>\n<li>\u652f\u6301\u591a\u7a97\u53e3\uff1a\u5728 <code>Info.plist<\/code> \u4e2d\u5f00\u542f <code>Application Scene Manifest<\/code> \u2192 <code>Enable Multiple Windows<\/code> = YES\uff1b<\/li>\n<li>\u786e\u4fdd\u6bcf\u4e2a\u7a97\u53e3\u7684 SplitView \u72ec\u7acb\u5de5\u4f5c\uff0c\u4e0d\u5171\u4eab\u72b6\u6001\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u952e\u76d8\/\u6307\u9488\u4ea4\u4e92\u9002\u914d<\/strong><\/p>\n<ul>\n<li>\u9876\u90e8\u5bfc\u822a\u652f\u6301\u786c\u4ef6\u952e\u76d8\u5feb\u6377\u952e\uff08\u5982 <code>Cmd+1<\/code> \u8df3\u8f6c\u5230\u9996\u9875\uff09\uff1a\n<pre><code class=\"language-swift\">override var keyCommands: [UIKeyCommand]? {\n return [\n     UIKeyCommand(input: \"1\", modifierFlags: .command, action: #selector(jumpToHome)),\n     UIKeyCommand(input: \"2\", modifierFlags: .command, action: #selector(jumpToDocument))\n ]\n}<\/code><\/pre>\n<\/li>\n<li>\u4e3a\u4fa7\u8fb9\u680f\/\u9876\u90e8\u5bfc\u822a\u6309\u94ae\u6dfb\u52a0\u6307\u9488\u60ac\u505c\u6548\u679c\uff1a\n<pre><code class=\"language-swift\">let pointerInteraction = UIPointerInteraction(delegate: self)\naddBtn.addInteraction(pointerInteraction)<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>\u56db\u3001\u66ff\u4ee3\u65b9\u6848\uff08\u975e\u539f\u751f\uff09<\/h3>\n<p>\u5982\u679c\u9700\u8981\u66f4\u81ea\u5b9a\u4e49\u7684\u4fa7\u8fb9\u680f\uff08\u5982\u53ef\u62d6\u62fd\u5bbd\u5ea6\u3001\u81ea\u5b9a\u4e49\u6837\u5f0f\uff09\uff0c\u53ef\u4f7f\u7528\u7b2c\u4e09\u65b9\u5e93\uff1a<\/p>\n<ul>\n<li><code>SideMenu<\/code>\uff1a\u8f7b\u91cf\u7ea7\u81ea\u5b9a\u4e49\u4fa7\u8fb9\u680f\uff0c\u652f\u6301 iPad \u5206\u5c4f\u9002\u914d\uff1b<\/li>\n<li><code>SwiftUI<\/code> \u65b9\u6848\uff1a\u7528 <code>NavigationSplitView<\/code> \u66ff\u4ee3 <code>UISplitViewController<\/code>\uff0c\u4ee3\u7801\u66f4\u7b80\u6d01\uff08iOS 16+ \u652f\u6301\uff09\uff1a\n<pre><code class=\"language-swift\">struct ContentView: View {\n  var body: some View {\n      NavigationSplitView {\n          \/\/ \u4fa7\u8fb9\u680f\n          List(menuItems) { item in\n              NavigationLink(item.title, destination: DetailView(item: item))\n          }\n          .listRowHeight(60)\n      } detail: {\n          \/\/ \u8be6\u60c5\u533a\uff08\u9876\u90e8\u5bfc\u822a + \u5185\u5bb9\uff09\n          NavigationStack {\n              HomeView()\n                  .navigationTitle(\"\u9996\u9875\")\n                  .navigationBarTitleDisplayMode(.large)\n          }\n      }\n  }\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<h3>\u603b\u7ed3<\/h3>\n<p>\u6838\u5fc3\u662f\u901a\u8fc7 <code>UISplitViewController<\/code>\uff08\u6216 SwiftUI \u7684 <code>NavigationSplitView<\/code>\uff09\u5b9e\u73b0\u300c\u4fa7\u8fb9\u680f\uff08\u4e00\u7ea7\uff09+ \u9876\u90e8\u5bfc\u822a\uff08\u4e8c\u7ea7\/\u4e09\u7ea7\uff09\u300d\u7684\u7ed3\u6784\uff0c\u517c\u987e iPad \u5927\u5c4f\u7684\u7a7a\u95f4\u4f18\u52bf\u548c\u5206\u5c4f\/\u7ad6\u5c4f\u7684\u6298\u53e0\u573a\u666f\u3002\u5173\u952e\u662f<strong>\u9002\u914d\u4e0d\u540c\u5c3a\u5bf8\u4e0b\u7684\u5bfc\u822a\u5165\u53e3\u4e0d\u4e22\u5931<\/strong>\u3001<strong>\u63a7\u4ef6\u5c3a\u5bf8\u7b26\u5408 iPad \u89e6\u63a7\u4e60\u60ef<\/strong>\u3001<strong>\u4ea4\u4e92\u903b\u8f91\u8d34\u8fd1\u684c\u9762\u7aef\u6548\u7387<\/strong>\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728 iPad \u4e0a\u66ff\u4ee3\u201c\u5e95\u90e8 TabBar \u4e3b\u5bfc\u822a\u201d\u3001\u5b9e\u73b0\u300c\u4fa7\u8fb9\u680f + \u9876\u90e8\u5bfc\u822a\u300d\u7684\u591a\u5c42\u7ea7\u9ad8\u6548\u5bfc\u822a\uff0c\u6838\u5fc3\u662f\u5229\u7528 &#8230; <\/p>\n<div class=\"read-more navbutton\"><a href=\"https:\/\/t.n-years.com\/?p=6936\">\u9605\u8bfb\u66f4\u591a<i class=\"fa fa-angle-double-right\"><\/i><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[135],"tags":[],"class_list":["post-6936","post","type-post","status-publish","format-standard","hentry","category-135"],"_links":{"self":[{"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/posts\/6936","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/t.n-years.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6936"}],"version-history":[{"count":1,"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/posts\/6936\/revisions"}],"predecessor-version":[{"id":6937,"href":"https:\/\/t.n-years.com\/index.php?rest_route=\/wp\/v2\/posts\/6936\/revisions\/6937"}],"wp:attachment":[{"href":"https:\/\/t.n-years.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6936"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/t.n-years.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6936"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/t.n-years.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6936"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}