You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中实现可搜索文本并跳转带搜索文本新视图的问题排查

问题描述

我正在开发一款提供选择功能的SwiftUI应用,用户选择颜色后会跳转至新视图,视图内容由文本参数决定。我希望通过SwiftUI搜索栏实现该功能:用户输入时显示可选选项。但当前代码存在问题:无论选择什么内容,仅显示选中项,且底部的“Go”按钮始终不可用(呈灰色文本状态)。

当前代码

struct ContentView: View {
    let colors = ["Blue", "Cyan", "Teal", "Mint", "Green", "Yellow", "Orange", "Red", "Pink", "Purple", "Indigo"]
    
    var filteredColors: [String] { // 1
        if queryString.isEmpty {
            return colors
        } else {
            return colors.filter { $0.localizedCaseInsensitiveContains(queryString) }
        }
    }
    
    @State private var queryString = ""
    @State private var goToSecondView = false
    
    
    var body: some View {
        NavigationView {
            List(filteredColors, id: \.self) { color in
                Text(color)
            }
            .navigationTitle("Colors")
            .searchable(text: $queryString, prompt: "Color Search", suggestions: {
                ForEach(colors.filter { $0.localizedCaseInsensitiveContains(queryString) } , id: \.self) { suggestion in
                    Text(suggestion)
                        .searchCompletion(suggestion)
                }
            })
            .onSubmit(of: .search) { // 1
                print("submit")
                goToSecondView = true
            }
        }
        NavigationLink {
            if goToSecondView {
                SecondView(querystring: queryString)
            }
        } label: {
            Text("Go")
        }
    }
}

struct SecondView : View {
    var querystring : String
    var body : some View {
        Text(querystring)
    }
}
问题分析与修复方案

核心问题点

  1. 选中后列表仅显示单项:
    当前用queryString同时承担搜索输入和选中值的角色,导致过滤后的列表始终只匹配queryString的内容。用户选择颜色后,queryString被设置为选中的颜色,列表自然只剩这一项,不符合预期。

  2. Go按钮不可用且逻辑错误:

    • NavigationLink被放在NavigationView外部,脱离了SwiftUI的导航上下文,导致按钮无法正常响应导航逻辑。
    • 用goToSecondView条件渲染目标视图,不符合NavigationLink的工作机制,同时没有任何逻辑控制按钮的启用状态。

修复后的代码

struct ContentView: View {
    let colors = ["Blue", "Cyan", "Teal", "Mint", "Green", "Yellow", "Orange", "Red", "Pink", "Purple", "Indigo"]
    
    var filteredColors: [String] {
        if queryString.isEmpty {
            return colors
        } else {
            return colors.filter { $0.localizedCaseInsensitiveContains(queryString) }
        }
    }
    
    @State private var queryString = ""
    @State private var selectedColor: String? // 单独存储选中的颜色
    @State private var isNavigating = false
    
    var body: some View {
        NavigationView {
            List(filteredColors, id: \.self) { color in
                Text(color)
                    .onTapGesture {
                        selectedColor = color
                        queryString = color // 可选:点击列表项时同步到搜索框
                    }
            }
            .navigationTitle("Colors")
            .searchable(text: $queryString, prompt: "Color Search", suggestions: {
                ForEach(colors.filter { $0.localizedCaseInsensitiveContains(queryString) }, id: \.self) { suggestion in
                    Text(suggestion)
                        .searchCompletion(suggestion)
                        .onTapGesture {
                            selectedColor = suggestion
                            queryString = suggestion
                        }
                }
            })
            // 将Go按钮放入导航工具栏,纳入导航上下文
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    NavigationLink(isActive: $isNavigating) {
                        if let color = selectedColor {
                            SecondView(querystring: color)
                        } else {
                            EmptyView()
                        }
                    } label: {
                        Text("Go")
                    }
                    // 只有选中颜色后才启用按钮
                    .disabled(selectedColor == nil)
                }
            }
            .onSubmit(of: .search) {
                // 搜索提交时自动匹配并选中颜色,触发跳转
                if let matchedColor = colors.first(where: { $0.localizedCaseInsensitiveContains(queryString) }) {
                    selectedColor = matchedColor
                    isNavigating = true
                }
            }
        }
    }
}

struct SecondView : View {
    var querystring : String
    var body : some View {
        Text("Selected Color: \(querystring)")
            .navigationTitle("Result")
    }
}

修复说明

  • 新增selectedColor变量,专门存储用户选中的颜色,与搜索输入的queryString分离,保证列表过滤逻辑不受选中状态影响。
  • 将NavigationLink移至NavigationView的底部工具栏中,确保处于导航上下文内,同时通过disabled修饰符控制按钮可用性——只有选中颜色后按钮才会启用。
  • 为列表项和搜索建议添加点击手势,点击时同步设置selectedColor,确保选中操作能正确记录值。
  • 优化搜索提交逻辑:用户提交搜索时,自动匹配并选中对应颜色,直接触发跳转,提升交互体验。

内容的提问来源于stack exchange,提问作者Philip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:36:17