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

iOS SwiftUI searchable修饰符提交后建议令牌未消失问题

带令牌的searchable提交搜索后建议令牌列表不消失的问题

问题现象

使用带令牌的searchable视图修饰符时,预期行为是:

  • 激活搜索字段时,建议令牌列表显示在结果列表上方
  • 选择令牌并提交搜索(按回车)后,建议列表消失,结果视图重新显示

但实际出现的问题是:提交搜索后,建议令牌仍遮挡结果视图,仅能通过取消搜索关闭令牌列表(此操作会丢弃当前搜索查询)。

测试环境:iPad(iOS 16.4)模拟器及真机,真机曾间歇性正常,目前提交搜索后令牌视图均不消失,软硬键盘均已测试。

可复现代码

struct SearchableTest: View {
    @StateObject private var filterModel = TestFilterModel()
    
    var body: some View {
        NavigationSplitView {
            List {
                Text("Testrow 1")
                Text("Testrow 2")
            }
            .searchable(text: $filterModel.searchFilter,
                        tokens: $filterModel.selectedTokens,
                        suggestedTokens: $filterModel.suggestedTokens,
                        placement: .navigationBarDrawer,
                        prompt: "Search",
                        token: { $0.tokenLabel })
        } detail: {
            Text("Detail View")
        }
        .task { filterModel.load() }
    }
}


@MainActor final class TestFilterModel: ObservableObject {
    @Published var searchFilter = ""
    @Published var selectedTokens = [TestFilterToken]()
    @Published var suggestedTokens = [TestFilterToken]()
    
    func load() {
        self.suggestedTokens = [
            .itemType("Type 1"),
            .itemType("Type 2"),
            .itemType("Type 3"),
            .status("Status 1"),
            .status("Status 2"),
            .status("Status 3"),
        ]
    }
}

// ======================================================= //
// MARK: - Tokens
// ======================================================= //
enum TestFilterToken: Identifiable {
    case itemType(String)
    case status(String)
    
    var id: String { self.title }
    
    var tokenLabel: Label<Text, Image> {
        Label(title, systemImage: systemImage)
    }
    
    var title: String {
        switch self {
        case let .itemType(string), let .status(string):
            return string
        }
    }
    
    var systemImage: String {
        switch self {
        case .itemType:
            return "circle.fill"
        case .status:
            return "square.fill"
        }
    }
}

问题分析

推测问题源于iOS 16.4中,键盘回车键的搜索提交行为未正确触发搜索字段失焦,导致建议令牌列表仍保持显示状态。此前正常时回车键显示“search”,按下可关闭建议视图,当前版本该行为出现异常。

解决方案

通过@FocusState控制搜索字段的焦点状态,在搜索提交时手动让搜索字段失去焦点,从而关闭建议令牌列表:

修改后的完整代码

struct SearchableTest: View {
    @StateObject private var filterModel = TestFilterModel()
    // 添加焦点状态变量
    @FocusState private var isSearchFocused: Bool
    
    var body: some View {
        NavigationSplitView {
            List {
                Text("Testrow 1")
                Text("Testrow 2")
            }
            .searchable(text: $filterModel.searchFilter,
                        tokens: $filterModel.selectedTokens,
                        suggestedTokens: $filterModel.suggestedTokens,
                        placement: .navigationBarDrawer,
                        prompt: "Search",
                        token: { $0.tokenLabel })
            // 绑定焦点状态
            .focused($isSearchFocused)
            // 监听搜索提交事件,手动失焦
            .onSubmit(of: .search) {
                isSearchFocused = false
            }
        } detail: {
            Text("Detail View")
        }
        .task { filterModel.load() }
    }
}


@MainActor final class TestFilterModel: ObservableObject {
    @Published var searchFilter = ""
    @Published var selectedTokens = [TestFilterToken]()
    @Published var suggestedTokens = [TestFilterToken]()
    
    func load() {
        self.suggestedTokens = [
            .itemType("Type 1"),
            .itemType("Type 2"),
            .itemType("Type 3"),
            .status("Status 1"),
            .status("Status 2"),
            .status("Status 3"),
        ]
    }
}

// ======================================================= //
// MARK: - Tokens
// ======================================================= //
enum TestFilterToken: Identifiable {
    case itemType(String)
    case status(String)
    
    var id: String { self.title }
    
    var tokenLabel: Label<Text, Image> {
        Label(title, systemImage: systemImage)
    }
    
    var title: String {
        switch self {
        case let .itemType(string), let .status(string):
            return string
        }
    }
    
    var systemImage: String {
        switch self {
        case .itemType:
            return "circle.fill"
        case .status:
            return "square.fill"
        }
    }
}

说明

  • 添加@FocusState private var isSearchFocused: Bool来跟踪搜索字段的焦点状态
  • 通过.focused($isSearchFocused)将焦点状态绑定到搜索字段
  • 使用.onSubmit(of: .search)监听搜索提交动作,触发时将isSearchFocused设为false,让搜索字段失焦,从而自动隐藏建议令牌列表

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:35:36