SwiftUI 从另一个视图中捕获 Picker 值
SwiftUI Catch the Picker value from another view
我需要向选择器添加搜索栏和零值。我想创建一个自定义选择器并在任何地方使用它以避免代码重复。我能够使用 and this 代码创建一个选择器,但我找不到如何捕获我在另一个视图中选择的值。
此代码帮助我在选择器中进行搜索。
struct SearchBar: UIViewRepresentable {
@Binding var text: String
var placeholder: String
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
searchBar.placeholder = placeholder
searchBar.autocapitalizationType = .none
searchBar.searchBarStyle = .minimal
return searchBar
}
func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
func makeCoordinator() -> SearchBar.Coordinator {
return Coordinator(text: $text)
}
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
}
这是我创建的自定义选择器。
struct CustomPicker<Item>: View where Item: Hashable {
let items: [Item]
let title: String
let text: KeyPath<Item, String>
let needOptional: Bool
let needSearchBar: Bool
@State var item: Item? = nil
@State var searchText: String = ""
var filteredItems: [Item] {
items.filter {
searchText.isEmpty ? true : [=11=][keyPath: text].lowercased().localizedStandardContains(searchText.lowercased())
}
}
var body: some View {
Picker(selection: $item, label: Text(title)) {
if needSearchBar {
SearchBar(text: $searchText, placeholder: "Search")
.padding(.horizontal, -12)
}
if needOptional {
Text("[none]").tag(nil as Item?)
.foregroundColor(.red)
}
ForEach(filteredItems, id: \.self) { item in
Text(item[keyPath: text])
.tag(item as Item?)
}
}
.onAppear{
searchText = ""
}
}
}
用法
国家模型示例
struct Country: Codable, Identifiable, Hashable {
let id = UUID()
let name: String
enum CodingKeys: String, CodingKey {
case id, name
}
}
在内容视图中
Form {
CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true)
}
如何在 ContentView 中捕获选定的项目(可选)?
使用@Binding
绑定您的物品。
struct CustomPicker<Item>: View where Item: Hashable {
let items: [Item]
let title: String
let text: KeyPath<Item, String>
let needOptional: Bool
let needSearchBar: Bool
@Binding var item: Item? // <--Here
@State var searchText: String = ""
//-----Other code---------//
并在内容视图中使用 @State
获取所选值。
struct ContentView: View {
@State private var selectedItem: Country? //<-- Here
private let countryArray: [Country] = [.init(name: "A"), .init(name: "B")]
var body: some View {
Form {
CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true, item: $selectedItem) // <-- Here
if let selectedItem = selectedItem {
Text(selectedItem.name)
}
}
}
}
我需要向选择器添加搜索栏和零值。我想创建一个自定义选择器并在任何地方使用它以避免代码重复。我能够使用
此代码帮助我在选择器中进行搜索。
struct SearchBar: UIViewRepresentable {
@Binding var text: String
var placeholder: String
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
searchBar.placeholder = placeholder
searchBar.autocapitalizationType = .none
searchBar.searchBarStyle = .minimal
return searchBar
}
func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
func makeCoordinator() -> SearchBar.Coordinator {
return Coordinator(text: $text)
}
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
}
这是我创建的自定义选择器。
struct CustomPicker<Item>: View where Item: Hashable {
let items: [Item]
let title: String
let text: KeyPath<Item, String>
let needOptional: Bool
let needSearchBar: Bool
@State var item: Item? = nil
@State var searchText: String = ""
var filteredItems: [Item] {
items.filter {
searchText.isEmpty ? true : [=11=][keyPath: text].lowercased().localizedStandardContains(searchText.lowercased())
}
}
var body: some View {
Picker(selection: $item, label: Text(title)) {
if needSearchBar {
SearchBar(text: $searchText, placeholder: "Search")
.padding(.horizontal, -12)
}
if needOptional {
Text("[none]").tag(nil as Item?)
.foregroundColor(.red)
}
ForEach(filteredItems, id: \.self) { item in
Text(item[keyPath: text])
.tag(item as Item?)
}
}
.onAppear{
searchText = ""
}
}
}
用法
国家模型示例
struct Country: Codable, Identifiable, Hashable {
let id = UUID()
let name: String
enum CodingKeys: String, CodingKey {
case id, name
}
}
在内容视图中
Form {
CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true)
}
如何在 ContentView 中捕获选定的项目(可选)?
使用@Binding
绑定您的物品。
struct CustomPicker<Item>: View where Item: Hashable {
let items: [Item]
let title: String
let text: KeyPath<Item, String>
let needOptional: Bool
let needSearchBar: Bool
@Binding var item: Item? // <--Here
@State var searchText: String = ""
//-----Other code---------//
并在内容视图中使用 @State
获取所选值。
struct ContentView: View {
@State private var selectedItem: Country? //<-- Here
private let countryArray: [Country] = [.init(name: "A"), .init(name: "B")]
var body: some View {
Form {
CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true, item: $selectedItem) // <-- Here
if let selectedItem = selectedItem {
Text(selectedItem.name)
}
}
}
}