来自本地 JSON 文件的 SwiftUI 搜索字段
SwiftUI search field from a local JSON file
我正在尝试从本地 JSON 文件中检索数据,如下所示:
[{
"name": "John",
"lastname": "Doe",
"age": "30"
},
{
"name": "Jane",
"lastname": "Doe",
"age": "20"
}
,
{
"name": "Baby",
"lastname": "Doe",
"age": "3"
}]
用户,使用数据选择器可以select姓名and/or姓氏
import SwiftUI
struct ContentView : View {
var names = ["John", "Jane", "Baby"]
var lastnames = ["Doe", "Boe"]
@State private var selectedNameItem = 0
@State private var selectedLastNameItem = 0
var body: some View {
VStack {
Picker(selection: $selectedNameItem, label: Text("Names:")) {
ForEach(0 ..< names.count) {
Text(self.names[[=12=]]).tag([=12=])
}
}
Text("Your choice: ")
+ Text("\(names[selectedNameItem])")
}
VStack {
Picker(selection: $selectedLastNameItem, label: Text("LastName:")) {
ForEach(0 ..< lastnames.count) {
Text(self.lastnames[[=12=]]).tag([=12=])
}
}
Text("Your choice: ")
+ Text("\(lastnames[selectedLastNameItem])")
}
}
}
一旦 select 编辑了 name/lastyname(作为参数),我想显示一个文本,例如:"John Doe is 30 years old"
如何在不列出所有元素的情况下从 JSON 和 return 准确读取用户 select 的年龄?
非常感谢,
法布里齐奥
首先,我建议创建一个结构来表示您的 JSON 结构。尝试以下操作:
struct Person: Codable, Hashable {
let name: String
let lastname: String
let age: String
}
typealias People = [Person]
我通常做一个typealias
来处理我的数据的数组版本。一旦你定义了你的数据结构来匹配你的 JSON,我通常会扩展我的数据,以便从 JSON 加载。
extension Person {
static func load(fromJson json: URL) -> People {
guard let data = try? Data(contentsOf: json) else {
preconditionFailure("Unable to read data from URL")
}
let jsonDecoder = JSONDecoder()
var people = People()
do {
people = try jsonDecoder.decode(People.self, from: data)
} catch {
print(error)
}
return people
}
}
有更通用的方法可以支持更广泛的模型,但对于您的示例来说,这既快速又简单。
现在您已经有了一种使用模型的简单方法,可以通过像这样扩展 Array 类型来轻松解决您的想法:
extension Array where Element == Person {
func retrievePeople(byName name: String) -> People {
return self.filter { [=12=].name == name }
}
func retrievePeople(byLastName lastname: String) -> People {
return self.filter { [=12=].lastname == lastname }
}
func retrievePeople(byAge age: String) -> People {
return self.filter { [=12=].age == age }
}
}
这将允许您通过任何元素查询整个对象范围,进而 return 匹配数组。如果您确定只有一个 return,您可以使用以下代码获取第一个元素:
// Let's assume your array of people is stored in this variable
var myPeople: People
if let person = myPeople.retrievePeople(byName: "John").first {
// Do the things you want with this person object here
}
这种带数据的loading/working风格的好处在于它易于快速生成,并且支持returning 0个对象、1个对象和多个对象。这也将允许您移动模型以使用 SwiftUI/Combine 的功能(这就是您希望在上面执行的操作)。
我正在尝试从本地 JSON 文件中检索数据,如下所示:
[{
"name": "John",
"lastname": "Doe",
"age": "30"
},
{
"name": "Jane",
"lastname": "Doe",
"age": "20"
}
,
{
"name": "Baby",
"lastname": "Doe",
"age": "3"
}]
用户,使用数据选择器可以select姓名and/or姓氏
import SwiftUI
struct ContentView : View {
var names = ["John", "Jane", "Baby"]
var lastnames = ["Doe", "Boe"]
@State private var selectedNameItem = 0
@State private var selectedLastNameItem = 0
var body: some View {
VStack {
Picker(selection: $selectedNameItem, label: Text("Names:")) {
ForEach(0 ..< names.count) {
Text(self.names[[=12=]]).tag([=12=])
}
}
Text("Your choice: ")
+ Text("\(names[selectedNameItem])")
}
VStack {
Picker(selection: $selectedLastNameItem, label: Text("LastName:")) {
ForEach(0 ..< lastnames.count) {
Text(self.lastnames[[=12=]]).tag([=12=])
}
}
Text("Your choice: ")
+ Text("\(lastnames[selectedLastNameItem])")
}
}
}
一旦 select 编辑了 name/lastyname(作为参数),我想显示一个文本,例如:"John Doe is 30 years old"
如何在不列出所有元素的情况下从 JSON 和 return 准确读取用户 select 的年龄?
非常感谢, 法布里齐奥
首先,我建议创建一个结构来表示您的 JSON 结构。尝试以下操作:
struct Person: Codable, Hashable {
let name: String
let lastname: String
let age: String
}
typealias People = [Person]
我通常做一个typealias
来处理我的数据的数组版本。一旦你定义了你的数据结构来匹配你的 JSON,我通常会扩展我的数据,以便从 JSON 加载。
extension Person {
static func load(fromJson json: URL) -> People {
guard let data = try? Data(contentsOf: json) else {
preconditionFailure("Unable to read data from URL")
}
let jsonDecoder = JSONDecoder()
var people = People()
do {
people = try jsonDecoder.decode(People.self, from: data)
} catch {
print(error)
}
return people
}
}
有更通用的方法可以支持更广泛的模型,但对于您的示例来说,这既快速又简单。
现在您已经有了一种使用模型的简单方法,可以通过像这样扩展 Array 类型来轻松解决您的想法:
extension Array where Element == Person {
func retrievePeople(byName name: String) -> People {
return self.filter { [=12=].name == name }
}
func retrievePeople(byLastName lastname: String) -> People {
return self.filter { [=12=].lastname == lastname }
}
func retrievePeople(byAge age: String) -> People {
return self.filter { [=12=].age == age }
}
}
这将允许您通过任何元素查询整个对象范围,进而 return 匹配数组。如果您确定只有一个 return,您可以使用以下代码获取第一个元素:
// Let's assume your array of people is stored in this variable
var myPeople: People
if let person = myPeople.retrievePeople(byName: "John").first {
// Do the things you want with this person object here
}
这种带数据的loading/working风格的好处在于它易于快速生成,并且支持returning 0个对象、1个对象和多个对象。这也将允许您移动模型以使用 SwiftUI/Combine 的功能(这就是您希望在上面执行的操作)。