Declaring TextField and Toggle in a SwiftUI dynamic form(在SwiftUI动态表单中声明Textfield和Togger)
本文介绍了在SwiftUI动态表单中声明Textfield和Togger的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
4年后,我又回到了快速编程,一切都改变了。我一切都是从头学起。 我正在尝试解决一个变量绑定问题。我想用从API返回的字段构建一个动态表单。 代码:
import SwiftUI
struct Filter: Codable, Identifiable {
var id: Int
var name: String
var type: String
var defaultValue: Int
init(_ dictionary: [String: Any]) {
self.id = dictionary["id"] as? Int ?? 0
self.name = dictionary["name"] as? String ?? ""
self.type = dictionary["type"] as? String ?? ""
self.defaultValue = dictionary["defaultValue"] as? Int ?? 0
}
}
struct ContentView: View {
@State var filters:Array<Filter> = []
func load(){
guard let url = URL(string: "https://api.kierklosebastian.pl/") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do {
let decoder = JSONDecoder()
let model = try decoder.decode([Filter].self, from:
dataResponse)
self.filters = model;
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
var body: some View {
VStack{
Button(action: self.load, label: {
Text("Get json")
})
List{
ForEach(self.filters) { filter in
HStack{
Text("NAME: (filter.name)")
Text("TYPE: (filter.type)")
if filter.type == "textField" {
// TextField("", ???????)
}
if filter.type == "checkbox" {
// Toggle(isOn: ????????) {
// ""
// }
}
}
}
}
}
}
}
如何声明TextFiled和Togger变量?
推荐答案
Toggle
需要有一个boolean
绑定属性来确定切换是打开还是关闭。因此您需要为Filter
定义某个布尔属性。
struct Filter: Codable, Identifiable {
var id: Int
var name: String
var type: String
var defaultValue: Int
var isOn: Bool = false
init(_ dictionary: [String: Any]) {
self.id = dictionary["id"] as? Int ?? 0
self.name = dictionary["name"] as? String ?? ""
self.type = dictionary["type"] as? String ?? ""
self.defaultValue = dictionary["defaultValue"] as? Int ?? 0
self.isOn = (dictionary["type"] as? String ?? "") == "checkbox"
}
}
创建符合ObservableObject
的视图模型。
https://developer.apple.com/documentation/combine/observableobject
class FilterViewModel: ObservableObject {
@Published var filters:Array<Filter> = []
func load(){
guard let url = URL(string: "https://api.kierklosebastian.pl/") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do {
let decoder = JSONDecoder()
let model = try decoder.decode([Filter].self, from:
dataResponse)
self.filters = model;
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
}
并在ContentView
中使用它而不是@State var filters:Array<Filter> = []
。
struct FilterView: View {
@ObservedObject var viewModel = FilterViewModel()
-----
}
为ForEach
的内容创建一个新视图,并将viewModel和筛选器传递给它。在新视图中,查找当前筛选器的索引。
struct FilterDetailView: View {
@ObservedObject var viewModel: FilterViewModel
var filter: Filter
var indexOfFilter: Int {
self.viewModel.filters.firstIndex { $0 == filter}!
}
var body: some View {
HStack{
Text("NAME: (filter.name)")
Text("TYPE: (filter.type)")
if filter.type == "textField" {
TextField("TextField", text: self.$viewModel.filters[indexOfFilter].name)
}
if filter.type == "checkbox" {
Toggle(isOn: self.$viewModel.filters[indexOfFilter].isOn) {
Text("Toggle")
}
}
}
}
}
您还需要确认Equatable
。否则,您不能使用firstIndex { $0 == filter}!
struct Filter: Codable, Identifiable, Equatable {
}
完整代码
struct Filter: Codable, Identifiable, Equatable {
var id: Int
var name: String
var type: String
var defaultValue: Int
var isOn: Bool = false
init(_ dictionary: [String: Any]) {
self.id = dictionary["id"] as? Int ?? 0
self.name = dictionary["name"] as? String ?? ""
self.type = dictionary["type"] as? String ?? ""
self.defaultValue = dictionary["defaultValue"] as? Int ?? 0
self.isOn = (dictionary["type"] as? String ?? "") == "checkbox"
}
}
class FilterViewModel: ObservableObject {
@Published var filters:Array<Filter> = []
func load(){
guard let url = URL(string: "https://api.kierklosebastian.pl/") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do {
let decoder = JSONDecoder()
let model = try decoder.decode([Filter].self, from:
dataResponse)
self.filters = model;
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
}
struct FilterView: View {
@ObservedObject var viewModel = FilterViewModel()
var body: some View {
VStack{
Button(action: self.viewModel.load, label: {
Text("Get json")
})
List{
ForEach(self.viewModel.filters) { filter in
FilterDetailView(viewModel: viewModel, filter: filter)
}
}
}
}
}
struct FilterDetailView: View {
@ObservedObject var viewModel: FilterViewModel
var filter: Filter
var indexOfFilter: Int {
self.viewModel.filters.firstIndex { $0 == filter}!
}
var body: some View {
HStack{
Text("NAME: (filter.name)")
Text("TYPE: (filter.type)")
if filter.type == "textField" {
TextField("TextField", text: self.$viewModel.filters[indexOfFilter].name)
}
if filter.type == "checkbox" {
Toggle(isOn: self.$viewModel.filters[indexOfFilter].isOn) {
Text("Toggle")
}
}
}
}
}
iOS 15+
ForEach(self.viewModel.filters) { $filter in
-----
}
Toggle(isOn: $filter.isOn) {
Text("Toggle")
}
如果您感兴趣,请观看SwiftUI-WWDC21中的新功能(08:00)并遵循Apple的SwiftUI教程
- https://developer.apple.com/videos/play/wwdc2021/10018/
- https://developer.apple.com/tutorials/SwiftUI
这篇关于在SwiftUI动态表单中声明Textfield和Togger的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:在SwiftUI动态表单中声明Textfield和Togger
基础教程推荐
猜你喜欢
- Android:对话框关闭而不调用关闭 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01