如何增加 SwiftUI 选择器中显示的最大行数?

2024-02-26

我正在尝试创建一个 SwiftUI 选择器,用户可以使用它来选择 1000 到 20000 之间的数字(以 1000 为增量。例如 1000,2000,3000 .... ... 20000)

默认情况下,SwiftUI 选择器只能容纳 10 行文本。如何允许 SwiftUI 选择器包含 20 行文本?


我猜你写了这样的东西:

struct ContentView: View {
    var body: some View {
        Picker(selection: $value, label: Text("Pick One")) {
            Text("1000").tag(1000)
            Text("2000").tag(2000)
            Text("3000").tag(3000)
            Text("4000").tag(4000)
            Text("5000").tag(5000)
            Text("6000").tag(6000)
            Text("7000").tag(7000)
            Text("8000").tag(8000)
            Text("9000").tag(9000)
            Text("10000").tag(10000)
        }
    }

    @State var value: Int = 1000
}

然后您尝试添加 11000 行并收到此错误:

error: picker.xcplaygroundpage:5:31: error: cannot convert value of type 'Binding<Int>' to expected argument type 'Binding<_>'
            Picker(selection: $value, label: Text("Pick One")) {
                              ^~~~~~

问题是,由于 Swift 语言和 SwiftUI 实现方式的限制,一个视图中只能有 10 个子视图。@ViewBuilder body.

这里有两种方法可以解决这个问题。

适合您的设计的一种方法是使用ForEach:

struct ContentView: View {
    var body: some View {
        Picker(selection: $value, label: Text("Pick One")) {
            ForEach(Array(stride(from: 1000, through: 20000, by: 1000))) { number in
                Text("\(number)").tag(number)
            }
        }
    }

    @State var value: Int = 1000
}

如果您的项目不遵循简单的模式,另一种方法会更合适,那就是使用Group:

struct ContentView: View {
    var body: some View {
        Picker(selection: $value, label: Text("Pick One")) {
            Group {
                Text("1000").tag(1000)
                Text("2000").tag(2000)
                Text("3000").tag(3000)
                Text("4000").tag(4000)
                Text("5000").tag(5000)
                Text("6000").tag(6000)
                Text("7000").tag(7000)
                Text("8000").tag(8000)
                Text("9000").tag(9000)
                Text("10000").tag(10000)
            }
            Group {
                Text("11000").tag(11000)
                Text("12000").tag(12000)
                Text("13000").tag(13000)
                Text("14000").tag(14000)
                Text("15000").tag(15000)
                Text("16000").tag(16000)
                Text("17000").tag(17000)
                Text("18000").tag(18000)
                Text("19000").tag(19000)
                Text("20000").tag(20000)
            }
        }
    }

    @State var value: Int = 1000
}

SwiftUI 扁平化Group子视图进入Group的父级(在本例中,进入Picker). Each Group最多可以有 10 个子视图,它们本身可以是Groups,因此通过嵌套Group你可以在你的程序中包含任意多个显式元素Picker。但我建议使用ForEach.

如果您想了解 10 个子视图限制的来源,请编辑我的第二个示例,存储Picker在这样的变量中:

struct ContentView: View {
    var body: some View {
        let picker = Picker(selection: $value, label: Text("Pick One")) {
            Group {
            ...
            }
        }
        return picker
    }
}

现在按住 Option 键并单击pickerXcode 中的变量以查看其推断类型:

让我们重新格式化它,使其更具可读性:

let picker: Picker<
    Text,
    Int,
    TupleView<(
        Group<TupleView<(
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View)>>,
        Group<TupleView<(
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View,
            some View)>>)>>

哇,好大的类型啊! SwiftUI 大量使用这样的泛型类型,因为它在运行时效率更高。因为这些都是struct类型符合View, Swift 存储了整个Picker及其所有子项都位于一个连续的内存块中。该块可以从堆栈开始,仅当 SwiftUI 最终需要对其进行类型擦除或长期存储时,才需要将其复制到堆中。与 UIKit 相比,每个视图在创建时总是在堆上单独分配。

ViewBuilder https://developer.apple.com/documentation/swiftui/viewbuilder是组装这些复杂视图的 SwiftUI 实用程序。斯威夫特改变了每个人的身体Group拨打电话ViewBuilder.buildBlock,每个视图内Groupbody 作为一个单独的参数ViewBuilder.buildBlock。每个参数都可以是一个单独的类型(例如Group可以有一些Text儿童和一些Image孩子们)。但 Swift 不支持可变泛型,所以ViewBuilder必须定义一个版本buildBlock采用单个视图的版本,采用两个视图的版本,以及采用三个视图的版本,依此类推。它不能定义无限数量的方法,因为那样的话 SwiftUI 框架就会无限大。所以它停在 10 个参数处:

static func buildBlock() -> EmptyView
Builds an empty view from a block containing no statements.

static func buildBlock<Content>(Content) -> Content
Passes a single view written as a child view through unmodified.

static func buildBlock<C0, C1>(C0, C1) -> TupleView<(C0, C1)>
static func buildBlock<C0, C1, C2>(C0, C1, C2) -> TupleView<(C0, C1, C2)>
static func buildBlock<C0, C1, C2, C3>(C0, C1, C2, C3) -> TupleView<(C0, C1, C2, C3)>
static func buildBlock<C0, C1, C2, C3, C4>(C0, C1, C2, C3, C4) -> TupleView<(C0, C1, C2, C3, C4)>
static func buildBlock<C0, C1, C2, C3, C4, C5>(C0, C1, C2, C3, C4, C5) -> TupleView<(C0, C1, C2, C3, C4, C5)>
static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(C0, C1, C2, C3, C4, C5, C6) -> TupleView<(C0, C1, C2, C3, C4, C5, C6)>
static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7>(C0, C1, C2, C3, C4, C5, C6, C7) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7)>
static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8>(C0, C1, C2, C3, C4, C5, C6, C7, C8) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8)>
static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)>

这就是为什么任何其内容定义的视图ViewBuilder(包括VStack, HStack, ZStack, Picker, List, Group等)只能有 10 个直接子视图。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何增加 SwiftUI 选择器中显示的最大行数? 的相关文章

随机推荐

  • H2 控制台在 H2 数据库中抛出错误 webAllowOthers

    我正在使用heroku来部署我的应用程序 当我尝试使用heroku加载我的h2控制台时 它抛出一个错误 H2 控制台 抱歉 此服务器上禁用远程连接 webAllowOthers 我在 application properties 文件中使用
  • 防止 Web 应用程序升级时浏览器缓存

    我有一个非常麻烦的问题 目前还没有找到好的解决方案 我允许浏览器缓存所有应用程序静态文件 JS CSS 和图像 以提高性能 问题是 当我进行升级时 用户仍然使用缓存中的旧版本 这经常会破坏应用程序 并且每次都需要清除缓存才能解决问题 是否有
  • Python:Pandas - 按组删除第一行

    我有以下大型数据框 df 看起来像这样 ID date PRICE 1 10001 19920103 14 500 2 10001 19920106 14 500 3 10001 19920107 14 500 4 10002 199201
  • Scala 括号语义

    将值附加到 MAP 时 为什么 Scala 需要额外的括号块才能使该语句起作用 不编译 vmap item getName item getString compiler output found String 但是 这确实可以编译 vma
  • 在不使用内容辅助输入整行时,Eclipse 在光标前插入分号

    这种行为让我抓狂 我输入以下内容 fileName append c get Calendar HOUR OF DAY 现在 当我输入内容时 会弹出内容辅助 我没有从内容辅助中选择 HOUR OF DAY 也没有按 Enter 键自动填写
  • 在C中计算欧几里德距离矩阵

    我想将用 MATLAB 编写的代码转换为 C matrix 1 2 3 4 5 6 7 8 10 dis zeros 9 for i 1 3 for j 1 3 dis i j sqrt sum abs matrix i matrix j
  • 尝试从网络位置加载程序集,这会导致程序集被沙箱化

    Net 4 0 出现错误 尝试从网络位置加载程序集 会导致程序集被沙箱化 应用设置
  • 带有 IAM 的 AWS MSK - 超时异常

    我们正在使用 Aws MSK 最近他们宣布了 AWS MSK IAM AUTH https github com aws aws msk iam auth https github com aws aws msk iam auth 当我尝试
  • css动画为什么会改变z-index? [复制]

    这个问题在这里已经有答案了 为什么动画会改变 z index 如果您查看 jsfiddle 您会看到红色图像位于顶部 但如果注释掉动画 则蓝色图像位于顶部 即使有动画 如何才能使蓝色图像始终位于顶部 jsfiddle http jsfidd
  • 删除字符串中重复字符(单词)的最佳方法?

    删除字符串中任何重复字符和由空格分隔的字符集的最佳方法是什么 我认为这个例子更好地解释了这一点 foo h k k h2 h 应该变成 foo h k h2 order not important 其他例子 foo s s k become
  • 在 Windows 事件查看器中诊断 CLR 错误

    我们有一个 NET 桌面应用程序在生产中崩溃了 我们如何诊断错误 我想知道发生的异常类型 错误消息和堆栈跟踪 因为我们的代码没有处理异常 所以我们收到了 此应用程序遇到问题 需要关闭 Windows 消息框 唯一的选择就是关闭 没有调试按钮
  • 字符串匹配不同大小的 data.frames

    我有两个不同大小的 data frame 我正在寻找最有效的方法来将字符串从一个 data frame 匹配到另一个 data frame 并提取一些相关信息 这是一个例子 两个初始 data frames a 和 b 以及所需的结果 a
  • 如何使图像大小适应html表格中的行高

    我正在尝试制作一个强大的 html 签名以在 Thunderbird 中使用 我所说的稳健是指它不仅在 Thunderbird 中看起来正确 而且在我向其发送邮件的其他邮件客户端中也必须正确 例如 我使用 Gmail 进行了测试 布局非常简
  • ASP.Net Core 中的 AntiXSS

    Microsoft Web 保护库 AntiXSS https wpl codeplex com 已达到使用寿命 该页面指出 在 NET 4 0 中 框架中包含了一个 AntiXSS 版本 可以通过配置启用 在 ASP NET v5 中 基
  • PHP + Comet(长轮询)扩展/主机

    我使用 PHP MySQL 开发了一个应用程序 该应用程序使用了彗星技术 即长轮询 概念验证效果很好 但我预计流量会快速达到数千个同时连接 网络服务器上的数千个开放连接 我没有能力设置自己的服务器 例如使用 lighttpd 并且通常依赖简
  • 将自定义侦听器添加到 Kotlin 类的正确方法

    我是 Kotlin 菜鸟 第三天 正在尝试向我的班级添加一个侦听器 我目前正在使用 lambda 如下例所示 它们工作得很好 Declare callback class Controller var onAction gt Use cal
  • 有符号和无符号整数表达式的比较

    我刚刚开始使用 OpenGL 这是我的第一个代码 OpenGL hello program include
  • 如何确定复选框列表已选中/选中 -

    当我执行代码时 我得到 4 个复选框 并且我选中 选择了所有 4 个复选框 当我尝试调试代码时 它确实算作我有 4 个复选框 但所有 4 个复选框都被选中 false 我在代码中缺少什么
  • 检测项目中的循环依赖

    上次我在我的项目中发现了循环依赖问题 我解决了我的问题 但是我希望将来避免这种情况 我想到了在我的所有项目中发现循环依赖项并给我反馈的插件 Example 文件a js var functionFromA require b js cons
  • 如何增加 SwiftUI 选择器中显示的最大行数?

    我正在尝试创建一个 SwiftUI 选择器 用户可以使用它来选择 1000 到 20000 之间的数字 以 1000 为增量 例如 1000 2000 3000 20000 默认情况下 SwiftUI 选择器只能容纳 10 行文本 如何允许