SwiftUI:从显示滑动按钮的旧列表切换到新列表时,UI 不正确

2024-04-10

可以使用下面的代码一致地重现该问题。 Xcode 13.3 + iOS 15.4(都是最新的)。

enum ListID: String, CaseIterable, Hashable, Identifiable {
    case list1 = "List1"
    case list2 = "List2"
    
    var id: Self {
        self
    }
}

struct ContentView: View {
    @State var listID: ListID = .list1
    
    var body: some View {
        VStack {
            // 1) Picker
            Picker(selection: $listID) {
                ForEach(ListID.allCases) { id in
                    Text(id.rawValue)
                }
            } label: {
                Text("Select a list")
            }
            .pickerStyle(.segmented)
            // 2) List
            switch listID {
            case .list1:
                createList(Array(1...2), id: .list1)
            case .list2:
                createList(Array(101...102), id: .list2)
            }
        }

    }
    
    @ViewBuilder func createList(_ itemValues: [Int], id: ListID) -> some View {
        List {
            ForEach(itemValues, id:\.self) { value in
                Text("\(value)")
                    .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                        Button("Edit") {
                            // do nothing
                        }
                        .tint(.blue)
                    }
            }
        }
        .id(id)
    }
}

重现问题的步骤:

  1. 启动应用程序。见图1。
  2. 滑动列表 1 中的项目 1,保持“编辑”按钮不变(不要点击它)。见图2
  3. 然后在选择器中选择列表 2。您应该看到列表中的项目之前有一个额外的空格。此外,所有列表项都不再可滑动。见图3。
  4. 然后在选择器中选择列表 1。它有同样的问题。见图4。

该问题并非特定于选择器。例如,如果我们用一组按钮替换选择器,就可以重现它。我相信只有当旧列表在 SwiftUI 视图层次结构中被销毁时才会出现此问题。根据我对 SwiftUI 中结构化身份的理解,列表 1 和列表 2 被视为 SwiftUI 视图层次结构中的单独视图。因此尚不清楚它们如何相互影响。我能猜测的唯一原因是,虽然列表 1 和列表 2 被视为单独的虚拟视图,但 SwiftUI 实际上为它们使用相同的物理视图(例如,出于性能目的等)。所以对我来说这似乎是一个 SwiftUI 错误。

沿着这个思路思考,我可以通过不破坏列表来解决这个问题:

ZStack {
    createList(Array(1...2), id: .list1)
        .opacity(listID == .list1 ? 1 : 0)
    createList(Array(101...102), id: .list2)
        .opacity(listID == .list2 ? 1 : 0)
}

这在这个特定示例中完美运行,但不幸的是它不可扩展。例如,在我的日历应用程序中,当用户单击日历中的日期时,我想显示该日期的事件列表(我想对不同的日期使用不同的列表。我通过调用id()为每个列表设置不同的 id)。在这种情况下,没有明显/优雅的方法来应用上述解决方案。

所以我想知道是否有人知道如何以更通用的方式解决这个问题?谢谢。


我最终通过对不同列表使用单个虚拟视图来解决这个问题。为此,我需要将 List 移到外面switch声明(否则 SwiftUI 的结构化身份机制会将这两个列表视为不同的列表)。

该解决方法在我的测试中可靠地工作(包括在我的实际应用程序中进行测试)。它很干净而且一般。我更喜欢为每个列表分配不同的 id,因为我认为它在架构上更干净且更好,但不幸的是,在 Apple 修复该错误之前它无法使用。我已经提交了关于这个问题的FB9976079。

我将保持我的问题开放,并欢迎任何人留下您的答案或评论。

enum ListID: String, CaseIterable, Hashable, Identifiable {
    case list1 = "List1"
    case list2 = "List2"

    var id: Self {
        self
    }
}

struct ContentView: View {
    @State var listID: ListID = .list1

    var body: some View {
        VStack {
            // 1) Picker
            Picker(selection: $listID) {
                ForEach(ListID.allCases) { id in
                    Text(id.rawValue)
                }
            } label: {
                Text("Select a list")
            }
            .pickerStyle(.segmented)
            // 2) List
            List {
                switch listID {
                case .list1:
                    createSection(Array(1...2), id: .list1)
                case .list2:
                    createSection(Array(101...105), id: .list2)
                }
            }
        }

    }

    // Note: the id param is not used as List id.
    @ViewBuilder func createSection(_ itemValues: [Int], id: ListID) -> some View {
        Section {
            ForEach(itemValues, id:\.self) { value in
                Text("\(value)")
                    .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                        Button("Edit") {
                            // do nothing
                        }
                        .tint(.blue)
                    }
            }
        }
        .id(id)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI:从显示滑动按钮的旧列表切换到新列表时,UI 不正确 的相关文章

  • Swift - 将图像插入 PDF 不再适用于 iOS 13

    目前正在开发在我的贷款计算器应用程序上导出 PDF 的功能 我有一个预览屏幕 可以在您保存 PDF 之前显示它 预览屏幕由带有 html 的 webView 组成 其中包含占位符 我能够成功地将图像插入到正确的占位符上 并将其显示在 PDF
  • IOS 上图像的加密/解密

    我们正在使用加密 解密和 UIIMAGE 如果我们加密和解密 UIIMAge 而不保存到 iphone 画廊中 它工作正常 但如果我们加密 保存到画廊中 将 加密的图像 加载到应用程序中 然后解密它效果不好 我们使用这个函数来加密 解密 保
  • iOS 键盘显示后分屏宽度

    我刚刚开始研究 Cordova 应用程序对分屏多任务处理的支持 到目前为止 该应用程序在模拟器中的 iPad 上显示和调整大小都很好 但是当我单击编辑字段并显示软件键盘时 100 宽度的值开始返回整个屏幕 而不是给出的窗口 初始显示 到目前
  • 如何像谷歌日历一样将单元格的内容滚动到表格视图中的另一个单元格中?

    我希望用户界面像谷歌日历那样进入桌面视图 它在不同的行中显示相同的日期事件 但是当您向上或向下滚动时 左侧的日期也会向上向下滚动 Can you please help me how to achieve this Please take
  • ArraySlice 中的 Swift [重复]

    这个问题在这里已经有答案了 在数组上使用 prefix 方法后 我得到了所谓的 arraySlice 我怎样才能将其转换为数组 我试图从 FacebookGraphApi 获取 Ints 然后请求前 3 个 前缀 3 并尝试将它们添加到新数
  • 在SwiftUI中,如何高性能地绘制阴影?

    我用 shadow color radius x y 在我的应用程序中绘制阴影 这是我所知道的在 SwiftUI 中绘制应用程序的唯一方法 我用 sheet isPresented content 方法弹出一个视图 其中包含很多阴影 当我调
  • 如何在 SQLite 中替换字符串?

    如何更新具有以下内容的表列 var mobile 233KKFSDK3234 Documents Page jpg 并将其替换为 Documents Page jpg 在 SQLite 中 注意 所有文字 除了 Documents 是动态的
  • 无法安装企业应用程序 - 此配置文件无法安装在此设备上

    我正在设置 Jenkins 来构建应用程序的企业版本 以便在我们的内部应用程序商店中分发 如果我将应用程序存档在 Xcode 中 然后在手机上下载内置的 ipa 则应用程序安装不会出现任何问题 但是当我使用 Jenkins 生成的具有相同私
  • 有没有办法阻止 iOS 上的 Safari 在关闭时清除网站的 cookie?

    我的移动网络应用程序的一位用户抱怨说 每次他关闭手机屏幕后使用该应用程序时 他都必须重新登录该应用程序 发生的情况是 当屏幕关闭时 或者当您通过双击主页按钮并滑开 Safari 来完全关闭 Safari 时 Safari 会清除该网站的 C
  • 在 UITextView 上添加具有自定义间距和文本的图像

    I want to add Image on text view and want proper spacing as shown in screenshot 我尝试在文本视图上添加图像 但在根据要求放置文本时遇到问题 请向我提供有关同样的
  • 使用 for 循环填充 python 字典列表

    我试图用 for 循环填充字典列表 但最终结果显示 for 循环填充的最后一个字典覆盖了所有先前字典的值 我尝试调整以下中提出的解决方案 如何使用循环填充 Python 字典 https stackoverflow com question
  • iOS 11 浮动 TableView 标题

    有一个应用程序包含多个部分 展开 时每个部分有几行 折叠 时没有 每个部分都有一个部分标题 使用以下子类重用它们UITableViewHeaderFooterView等等 到目前为止一切顺利 然后在 iOS 11 中 我使用了可视化调试器
  • 除非在后台线程中获取新的引用,否则存在潜在的引用计数问题

    我有一个second https stackoverflow com questions 28898966 prefer property accessor or kvc style for accessing core data prop
  • UICollectionReusableView 方法未被调用

    我希望我的部分位于UICollectionView有一个带有图像的标题 我已按照以下步骤操作 在故事板中 分配了一个标题作为我的附件UICollectionView 给它一个标识符 创建了一个子类UICollectionReusableVi
  • ios 11 - UIBarButtonItem 内的 UIButton 导致自动布局错误

    我在将 UIButton 添加到 UIBarButtonItem 时遇到了一个已知问题 我尝试按照建议添加自动布局约束堆栈溢出 https stackoverflow com a 46336639 505603但我收到如下所述的错误 UIB
  • 断点条件错误

    我已经根据条件设置了断点 event name isEqualToString Some Name 这很好用 但是 当我尝试添加另一个带有条件的断点时 part name isEqualToString Some Value With A
  • 快速钥匙串更新只有在第二次尝试时才起作用

    您好 我在更新存储在钥匙串中的登录信息方面遇到了 iOS 钥匙串的一个非常奇怪的问题 因此 如果没有保存的凭据 则正确运行保存函数会保存登录信息 如果登录信息已存在并且用户更新了密码 则更新功能仅正确更新密码 但是 如果登录信息存在并且我尝
  • 使用 nib 作为带有 nib 类的表节标题

    我想创建一个加载 nib 文件并将其设置为标题 UIView 的节标题 这个 nib 文件还将有一个关联的类 其中插座和操作连接到 因此我想像平常一样使用 nib 加载该类 我在网上搜索并找到了几个类似的答案 但我找不到任何适合我的答案 经
  • iOS 13 检查 CLLocationManager 的临时授权状态

    根据 WWDC 视频 https developer apple com videos play wwdc2019 705 https developer apple com videos play wwdc2019 705 当你要求 Al
  • 如何在 Haskell 中制作打勾游戏的图案?

    实现有 2 个参数的函数 ticktick 第一个参数是自然数元组 定义游戏场地的行数和列数 第二个列表包含由玩家 x 和玩家 o 轮流玩的坐标给出的井字游戏比赛的记录 打印游戏的实际状态 其中游戏区域将由字符 和 界定 空方块 以及字符

随机推荐