Picker 中的 SwiftUI FetchRequest 订单输出
SwiftUI FetchRequest Order Output in Picker
我有一个 json 我正在从包含国家列表(以及 ID、国家名称和国家缩写)的远程服务器中获取。我正在通过 ForEach 使用这些值填充选择器。
我无法解决的两个问题是:
- 我想在选择器中将美国显示为首选,然后按字母顺序列出所有其他国家/地区。
我考虑过使用 NSPredicate 或 NSCompoundPredicate 但这只是过滤掉值。我考虑过创建多个获取请求并过滤除美国以外的所有内容,然后另一个显示除美国以外的所有内容。这似乎是一种浪费,而且我不完全确定如何将它们结合起来。
- 根据用户的选择,我需要填充三个变量(id、name 和 abbr)。
我可以绑定到名称,而且效果很好。同样,我可以将选择器绑定到缩写并且它可以工作。但是,我不知道如何更新所有 3 个变量,因为选择器只有一个绑定。我尝试编写一个函数来在 ForEach 中设置所有这些变量 onTap 但这似乎不是一个好计划(或者也许是?)。
这是一些代码:
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)] var countries: FetchedResults<Picker_Country>
// Load and decode the JSON from remote URL without caching
func loadCountryData() async {
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil
let URLSessionNoCache = URLSession(configuration: config)
guard let url = URL(string: "https://api.foo.com/general/pickers/country_select") else {
print("Invalid URL")
return
}
do {
let (data, _) = try await URLSessionNoCache.data(from: url)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let countries = try decoder.decode([CountryOptions].self, from: data)
await MainActor.run {
setCountryArray(with: countries)
}
} catch {
print("Invalid Data")
}
}
func setCountryArray(with downloadedCountryOptions: [CountryOptions]) {
for countries in downloadedCountryOptions {
let countryPicker = Picker_Country(context: moc)
countryPicker.id = Int16(countries.id)
countryPicker.name = countries.name
countryPicker.abbr = countries.abbr
}
try? moc.save()
}
最后,这是我的选择器。
(注意:wrappedName 和 wrappedAbbr 只是允许我不必合并 nil 的变量。它们直接对应于名称和缩写。)
显然,通过使用 .tag,我显示了名称,但仅设置了缩写,这也是选择所绑定的内容。这就是用户选择时如何设置id、name、abbr的问题。
Picker("Country", selection: $createUser.countryAbbr) {
ForEach(countries) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End ForEach
} // End Picker
.pickerStyle(WheelPickerStyle())
.padding()
.labelsHidden()
实际上比我想象的要简单得多。当您在不使用 ForEach 的情况下创建选择器时,您可以执行以下操作:
Picker("Fooblah", selection: $fooblah) {
Text("foo").tag(0)
Text("blah").tag(1)
} // End Picker
现在,因为 JSON 存储在 CoreData 中,我们可以使用 NSPredicate 来过滤 FetchRequest 的结果,您执行两个 FetchRequests,如下所示:
@FetchRequest(sortDescriptors: [], predicate: NSPredicate(format: "abbr == 'US'")) var countryUS: FetchedResults<Picker_Country>
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)], predicate: NSPredicate(format: "abbr != 'US'")) var countries: FetchedResults<Picker_Country>
第一个 FetchRequest returns 仅限美国,而第二个 returns 美国除外。
现在,当您创建选择器时,您会执行两个 ForEach 语句,就像您会执行两个或更多 Text 语句一样,如下所示:
Picker("Country", selection: $createUser.countryAbbr) {
ForEach(countryUS) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End US ForEach
ForEach(countries) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End All except US ForEach
} // End Picker
使用 CoreData 并绑定到国家/地区的缩写,然后您可以创建一个关系,以便在 managedObjectContext 中您可以调用相应的国家/地区名称,就像您可以调用国家/地区的缩写一样。
另一个提示是,如果您只想使用国家/地区缩写,但仍以某种方式显示完整的国家/地区名称,您可以通过内置的语言环境功能来实现,如下所示:
Text(Locale.current.localizedString(forRegionCode: createUser.countryAbbr) ?? createUser.countryAbbr)
现在这对于您希望在 CoreData 的选择器中显示的任何类型的结果都是灵活的。只需根据您的情况修改 NSPredicate 过滤器即可。
我有一个 json 我正在从包含国家列表(以及 ID、国家名称和国家缩写)的远程服务器中获取。我正在通过 ForEach 使用这些值填充选择器。
我无法解决的两个问题是:
- 我想在选择器中将美国显示为首选,然后按字母顺序列出所有其他国家/地区。
我考虑过使用 NSPredicate 或 NSCompoundPredicate 但这只是过滤掉值。我考虑过创建多个获取请求并过滤除美国以外的所有内容,然后另一个显示除美国以外的所有内容。这似乎是一种浪费,而且我不完全确定如何将它们结合起来。
- 根据用户的选择,我需要填充三个变量(id、name 和 abbr)。
我可以绑定到名称,而且效果很好。同样,我可以将选择器绑定到缩写并且它可以工作。但是,我不知道如何更新所有 3 个变量,因为选择器只有一个绑定。我尝试编写一个函数来在 ForEach 中设置所有这些变量 onTap 但这似乎不是一个好计划(或者也许是?)。
这是一些代码:
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)] var countries: FetchedResults<Picker_Country>
// Load and decode the JSON from remote URL without caching
func loadCountryData() async {
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil
let URLSessionNoCache = URLSession(configuration: config)
guard let url = URL(string: "https://api.foo.com/general/pickers/country_select") else {
print("Invalid URL")
return
}
do {
let (data, _) = try await URLSessionNoCache.data(from: url)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let countries = try decoder.decode([CountryOptions].self, from: data)
await MainActor.run {
setCountryArray(with: countries)
}
} catch {
print("Invalid Data")
}
}
func setCountryArray(with downloadedCountryOptions: [CountryOptions]) {
for countries in downloadedCountryOptions {
let countryPicker = Picker_Country(context: moc)
countryPicker.id = Int16(countries.id)
countryPicker.name = countries.name
countryPicker.abbr = countries.abbr
}
try? moc.save()
}
最后,这是我的选择器。
(注意:wrappedName 和 wrappedAbbr 只是允许我不必合并 nil 的变量。它们直接对应于名称和缩写。)
显然,通过使用 .tag,我显示了名称,但仅设置了缩写,这也是选择所绑定的内容。这就是用户选择时如何设置id、name、abbr的问题。
Picker("Country", selection: $createUser.countryAbbr) {
ForEach(countries) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End ForEach
} // End Picker
.pickerStyle(WheelPickerStyle())
.padding()
.labelsHidden()
实际上比我想象的要简单得多。当您在不使用 ForEach 的情况下创建选择器时,您可以执行以下操作:
Picker("Fooblah", selection: $fooblah) {
Text("foo").tag(0)
Text("blah").tag(1)
} // End Picker
现在,因为 JSON 存储在 CoreData 中,我们可以使用 NSPredicate 来过滤 FetchRequest 的结果,您执行两个 FetchRequests,如下所示:
@FetchRequest(sortDescriptors: [], predicate: NSPredicate(format: "abbr == 'US'")) var countryUS: FetchedResults<Picker_Country>
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)], predicate: NSPredicate(format: "abbr != 'US'")) var countries: FetchedResults<Picker_Country>
第一个 FetchRequest returns 仅限美国,而第二个 returns 美国除外。
现在,当您创建选择器时,您会执行两个 ForEach 语句,就像您会执行两个或更多 Text 语句一样,如下所示:
Picker("Country", selection: $createUser.countryAbbr) {
ForEach(countryUS) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End US ForEach
ForEach(countries) { country in
Text(country.wrappedName).tag(country.wrappedAbbr)
} // End All except US ForEach
} // End Picker
使用 CoreData 并绑定到国家/地区的缩写,然后您可以创建一个关系,以便在 managedObjectContext 中您可以调用相应的国家/地区名称,就像您可以调用国家/地区的缩写一样。
另一个提示是,如果您只想使用国家/地区缩写,但仍以某种方式显示完整的国家/地区名称,您可以通过内置的语言环境功能来实现,如下所示:
Text(Locale.current.localizedString(forRegionCode: createUser.countryAbbr) ?? createUser.countryAbbr)
现在这对于您希望在 CoreData 的选择器中显示的任何类型的结果都是灵活的。只需根据您的情况修改 NSPredicate 过滤器即可。