SwiftUI 列表(或 Form)子项中的 Picker 引起导航无法跳转的原因及解决

在这里插入图片描述

概述

在 SwiftUI 的界面布局中,列表(List)和 Form 是我们秃头码农们司空见惯的选择。不过大家是否知道:如果将 Picker 之类的视图嵌入到列表或 Form 的子项中会导致导航操作无法被触发。

在这里插入图片描述

从上图可以看到:当在 List 的子项中嵌入 Picker 时,所有互动操作都会聚焦在 Picker 上面,从而使得导航根本无法触发。

这种现象在 SwiftUI 6.0(iOS 18.1)中依然存在。

在本篇博文中,您将学到如下内容:

  • 概述
  • 1. 一个简单的问题
  • 2. “肿么”会这样?
  • 解决之道
  • 总结

想知道如何解决吗?超乎寻常的简单!
那还等什么呢?Let‘s go!!!😉


1. 一个简单的问题

首先是一段平淡无奇的的源代码:

enum JailConfig: Int, Identifiable, CaseIterable {
    case veryEasy = 1
    case easy
    case normal
    case hard
    case veryHard
    
    var id: Int {
        rawValue
    }
    
    var desc: String {
        switch self {
        case .veryEasy:
            "非常容易"
        case .easy:
            "容易"
        case .normal:
            "一般"
        case .hard:
            "有点难"
        case .veryHard:
            "很难"
        }
    }
}

@available(iOS 17, *)
struct V3_GameView: View {
    
    @State var jailConfig = JailConfig.normal
    
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("每日打卡") {
                    ClockInView()
                }
                
                NavigationLink("抓住机会") {
                    PressBlessingView(config: .normal)
                }
                
                NavigationLink {
                    FingersJail(config: jailConfig)
                } label: {
                    VStack(alignment: .leading) {
                        Text("指尖监狱")
                        LabeledContent {
                            Picker("", selection: $jailConfig) {
                                ForEach(JailConfig.allCases) { config in
                                    Text(config.desc).tag(config)
                                }
                            }
                            
                        } label: {
                            Text("难度")
                        }
                    }
                }
            }
            .listStyle(.plain)
            .navigationTitle("游戏")
            .toolbar {
                Text("大熊猫侯佩 @ \(Text("CSDN").foregroundStyle(.red))")
                    .foregroundStyle(.gray)
                    .font(.headline.bold())
            }
        }
    }
}

从代码中可以看到:我们在第 3 个列表项中嵌入了一个 Picker 视图,并将其包裹在 NavigationLink 的 label 中。这样做的意图是让用户在导航至子视图之前可以先选择一些配置信息(比如游戏难度)。

但这样简单的组合却带来了意想不到的“不良”结果:我们现在只能选择 Picker 的内容而无法进行导航了。

在这里插入图片描述

2. “肿么”会这样?

为了理解为何会如此,让我们先将布局稍微做一下调整。这次我们将 Picker 放在 NavigationLink 的外部:

VStack {
    NavigationLink {
        FingersJail(config: jailConfig)
    } label: {
        Text("指尖监狱")
    }
    
    LabeledContent {
        Picker("", selection: $jailConfig) {
            ForEach(JailConfig.allCases) { config in
                Text(config.desc).tag(config)
            }
        }
        
    } label: {
        Text("难度")
    }
}

再次运行代码可以看到:结果和之前一毛一样。为了确保这不是 Xcode 预览中的一个 Bug,我特地在模拟器中也运行了一下,毫无二致。


诸多关于 Xcode “蛋疼” 预览(Preview)机制的进一步介绍,请小伙伴们移步如下链接观赏精彩的内容:

  • SwiftUI 界面动画调试一例:做码农最重要的是什么?相信自己!
  • Xcode13模拟器和预览(Preview)导致Mac处理器占用率急剧飙升的解决方法
  • SwiftUI Xcode项目新增单元测试(Unit Test)后预览(Preview)崩溃的解决
  • Xcode预览(Preview)显示List视图内容的一个Bug及解决
  • Xcode如何在预览(Preview)调试中避免与SwiftUI正常运行时环境不一致导致的崩溃
  • Xcode编写SwiftUI代码时一个编译通过但导致预览(Preview)崩溃的小陷阱
  • Xcode 15 预览 SwiftUI 视图中 @FetchRequest 查询结果不能正确刷新的解决

看来目前 SwiftUI 布局中,在列表(或 Form)子项里 VStack(或其它容器)内部如果有类似 Picker 之类的可交互视图,其它视图的交互性将会受到抑制(除非其它视图是 borderless 样式的按钮)。

知道了原因解决起来就十分简单了:只需把它们分开就行啦!

解决之道

如下代码所示,我们可以将 Picker 和原先列表子项中显示的内容完全“分离”:

NavigationLink {
    FingersJail(config: jailConfig)
} label: {
    Text("指尖监狱")
}            

LabeledContent {
    Picker("", selection: $jailConfig) {
        ForEach(JailConfig.allCases) { config in
            Text(config.desc).tag(config)
        }
    }
    
} label: {
    Text("难度")
}
.padding(.top, -10)

不过,这样从界面上看会略显“割裂感”:

在这里插入图片描述

于是乎,我们可以用视图的 listRowSeparator 修改器隐藏中间的分隔线:

NavigationLink {
    FingersJail(config: jailConfig)
} label: {
    Text("指尖监狱")
}
.listRowSeparator(.hidden)

现在效果好极了:

在这里插入图片描述

或者我们可以将 Picker 和 NavigationLink 的内容统统放到一个 Section 中去,这样代码组织性会更好一些:

Section {
    NavigationLink {
        V3_FingersJail(config: jailConfig)
    } label: {
        Text("指尖监狱")
    }
    .listRowSeparator(.hidden)
    
    LabeledContent {
        Picker("", selection: $jailConfig) {
            ForEach(V3_JailConfig.allCases) { config in
                Text(config.desc).tag(config)
            }
        }
        
    } label: {
        Text("难度")
    }
    .padding(.top, -10)
}

至此,我们成功的解决了博文开头那个问题!希望可以一解小伙伴们的燃眉之急,棒棒哒!💯


想要系统学习 Swift 的小伙伴们,欢迎来我的《Swift 语言开发精讲》专栏逛一逛哦:

在这里插入图片描述

  • 《Swift 语言开发精讲》

总结

在本篇博文中,我们讨论了 SwiftUI 列表(或 Form)子项中的 Picker 导致无法导航跳转的原因,并随后给出完美的解决方案。

感谢观赏,再会吧!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/930767.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Elasticsearch入门到落地】3、es与mysql的概念对比

接上篇《2、正向索引和倒排索引》 上一篇我们学习了什么是正向索引和倒排索引。本篇我们来学习Elasticsearch与Mysql的概念与区别。 一、文档 Elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式…

云服务器部署upload-labs-docker(文件上传靶场)环境 以及相关报错问题

环境的搭建 准备:云服务器(本地的linux服务器(版本最好不要是老的不然不兼容docker)) f8x配置docker环境: https://github.com/ffffffff0x/f8x 一键配置 docker拉取file-labs靶场 https://github.com…

HAMR技术进入云存储市场!

2024年12月3日,Seagate宣布其Mozaic 3系列HAMR(热辅助磁记录)硬盘获得了来自一家领先云服务提供商(可能AWS、Azure或Google Cloud其中之一)以及其他高容量硬盘客户的资格认证。 Seagate的Mozaic 3技术通过引入热辅助磁…

【错误记录】Android Studio 开发环境内存占用过多 ( 记录内存使用情况 )

文章目录 一、报错信息二、AS 内存记录分析 一、报错信息 使用 Android Studio 一段时间后 , 内存爆了 , 占用了 10G 的内存 ; 二、AS 内存记录分析 AS 刚启动时 , 只占 2014M 内存 ; 编译运行程序后 , 内存变为 2800M 左右 ; 设置显示的运行程序对应的日志 , 占用内存 就会稳定…

BERT模型的实现

本文用 pytorch 实现一个BERT模型。 食用方法: 直接下载完整实现, 在自己本地跑一遍,保证不报错。先完成数据预处理阶段(1-4)的代码阅读,然后按照如下关键点的描述完成代码的实现。自己看着代码手写后续部…

VSCode GDB远程嵌入开发板调试

VSCode GDB远程嵌入式开发板调试 一、原理 嵌入式系统中一般在 PC端运行 gdb工具,源码也是在 PC端,源码对应的可执行文件放到开发板中运行。为此我们需要在开发板中运行 gdbserver,通过网络与 PC端的 gdb进行通信。因此要想在 PC上通过 gdb…

Hadoop3集群实战:从零开始的搭建之旅

目录 一、概念 1.1 Hadoop是什么 1.2 历史 1.3 三大发行版本(了解) 1.4 优势 1.5 组成💗 1.6 HDFS架构 1.7 YARN架构 1.8 MapReduce概述 1.9 HDFS\YARN\MapReduce关系 二、环境准备 2.1 准备模版虚拟机 2.2 安装必要软件 2.3 安…

RK3568笔记0:环境搭建

第1章 安装NFS服务器 NFS可以让不同的机器、不同的操作系统之间彼此共享文件 服务器安装NFS sudo apt-get install nfs-kernel-server服务器创建一个共享目录 sudo mkdir -p /home/lmz/workspaces/shared_directory配置共享目录到服务器中的配置文件中 sudo vim /etc/export…

Linux socket编程

目录 基础概念端口和端口号Socket(套接字)UDP和TCP的概念 Socket编程实战socket的类型struct sockaddrstruct sockaddr_in网络字节序socket APITCP网络编程流程分析UDP Demo样例 other概念补充setsockopt函数心跳机制面向字节流与面向报文的理解 参考 基…

OBS学习

OBS简介 OBS是Open Broadcaster Software的简称,是一款开源,用于视频录制以及直播串流的软件,它支持Windows、Mac以及Linux操作系统。 OBS使用场景 使用OBS软件,可以借助单反、摄像机、无人机等摄影设备在电脑上直播。OBS可以把…

SQL Server:调用的目标发生了异常。(mscorlib)

我之前安装的SQL Server是2014版本,SSMS运行也很流畅,有一次有个同事让我链接云服务器SQL地址,直接报上图的错误,把我弄的一愣一愣的。 后面才发现,这是版本太低导致的,但是你如果使用Navicat是没有问题的…

dolphinScheduler 任务调度

#Using docker-compose to Start Server #下载:https://dlcdn.apache.org/dolphinscheduler/3.1.9/apache-dolphinscheduler-3.1.9-src.tar.gz $ DOLPHINSCHEDULER_VERSION3.1.9 $ tar -zxf apache-dolphinscheduler-"${DOLPHINSCHEDULER_VERSION}"-src.t…

“为您的家电穿上防震铠甲:优质电器缓冲器

在地震频发地区或日常生活中,确保家电的安全和稳定至关重要。为了防止地震、意外碰撞或其他外力对家电造成损害,采用优质的电器缓冲器就像是为家电穿上了一层坚固的“防震铠甲”。这不仅能够有效减少因震动导致的损坏风险,还能显著延长家电的…

Qlib上手学习记录

Qlib 是一个面向人工智能的量化投资平台,其目标是通过在量化投资中运用AI技术来发掘潜力、赋能研究并创造价值,从探索投资策略到实现产品化部署。该平台支持多种机器学习建模范式,包括有监督学习、市场动态建模以及强化学习等。 真的是走了很…

web前端设计1

熟悉流行框架、熟练掌握CSS的写法,以及JAVASCRIPT库的应用,最主要的是能按要求改出相应的界面,因为我们基本没有自己手写代码的,所以得会拿别的界面改成想要的界面。 前端比较吃能力的就是CSS的写法,如何用已写好的框…

2020年国赛高教杯数学建模E题校园供水系统智能管理解题全过程文档及程序

2020年国赛高教杯数学建模 E题 校园供水系统智能管理 原题再现 校园供水系统是校园公用设施的重要组成部分,学校为了保障校园供水系统的正常运行需要投入大量的人力、物力和财力。随着科学技术的发展,校园内已经普遍使用了智能水表,从而可以…

JAVA |日常开发中连接Sqlite数据库详解

JAVA |日常开发中连接Sqlite数据库详解 前言一、SQLite 数据库概述1.1 定义与特点1.2 适用场景 二、Java 连接 SQLite 数据库的准备工作2.1 添加 SQLite JDBC 驱动依赖2.2 了解 JDBC 基础概念 三、建立数据库连接3.1 代码示例3.2 步骤解析 四、执行 SQL 语句4.1 创建…

图像超分辨率技术新进展:混合注意力聚合变换器HAAT

目录 1. 引言: 2. 混合注意力聚合变换器(HAAT): 2.1 Swin-Dense-Residual-Connected Block(SDRCB): 2.2 Hybrid Grid Attention Block(HGAB): 3. 实验结…

【Appium】AttributeError: ‘NoneType‘ object has no attribute ‘to_capabilities‘

目录 1、报错内容 2、解决方案 (1)检查 (2)报错原因 (3)解决步骤 3、解决结果 1、报错内容 在PyCharm编写好脚本后,模拟器和appium也是连接成功的,但是运行脚本时报错&…

1.1 Beginner Level学习之“创建 ROS msg 和 srv”(第十节)

学习大纲: 1. msg 和 srv msg 文件是描述 ROS 消息字段的简单文本文件。它们用于为不同语言生成消息的源代码。srv 文件则描述了一个服务,包括两部分:请求和响应。Srv 文件用于生成服务的源代码。msg 文件存储在包的 msg 目录中。srv 文件存…