在 swift ui 中创建 Json 数组
Posted
技术标签:
【中文标题】在 swift ui 中创建 Json 数组【英文标题】:Create Json array in swift ui 【发布时间】:2021-09-25 11:36:28 【问题描述】:我在列表中有一个复选框,单击复选框我想创建一个这样的 Json 数组
"nurseryData":["nurseryCode":"","SSOId":"",.....] and so on
我尝试了各种方法,但无法在单击复选框时附加参数。
请提出一种方法来实现它我是 swift ui 的初学者。
import SwiftUI
import Alamofire
struct AddNurseryCard: View
@State private var checked = false
let models : AddNurseryModels.Data
var data: [String: Any] = [
"nurseryData": [String : Any]()
]
var body: some View
HStack
Image("nursery")
Divider()
VStack
if((models.isUrban!) != 0)
Text(models.nurseryName! + " (U)")
else
Text(models.nurseryName! + " (R)")
Text(models.rANGE_NAME!)
if((models.isActiveForGGAY!) != 0)
Text("Is Active For GGAY : Yes")
else
Text("Is Active For GGAY : NO")
CheckBoxView(checked: $checked).onAppear()
if((models.isActiveForGGAY) != 0)
checked = true
else
checked = false
.onChange(of: checked, perform: value in
if(checked)
let result = UserDefaults.standard.value(forKey: "profile")
let profile = ProfileModels(dict: result as! [String : Any])
let ssoId = (profile.data?[0].ssoid ?? "") as String
let nurseryCode = models.nurseryCode!
var existingItems = data["nurseryCode"] as? [[String: Any]] ?? [[String: Any]]()
var param = ["ssoId":ssoId,"nurseryCode":nurseryCode]
param.merge(dict: param)
print()
existingItems.append(param)
print(existingItems)
addNursery(params: param)
)
Divider()
func getArray(params:[[String: Any]]) -> [[String: Any]]
return params
func getChecked() -> Bool
return checked
func getNurseryCode() -> String
return models.nurseryCode!
func addNursery(params :[String:Any])
let url = Constants.init().devUrl + Api.init().addNursery
let headers : HTTPHeaders = HTTPHeaders(["ApiKey" : Constants.init().apiKey])
AF.request(url,method: .post,parameters: params, encoding:JSONEncoding.default, headers: headers).responseJSON response in
switch response.result
case .failure(let error):
print(error)
case .success(let json):
print(json)
struct AddNurseryCard_Previews: PreviewProvider
static var previews: some View
AddNurseryCard(models: AddNurseryModels.dat)
extension Dictionary
mutating func merge(dict: [Key: Value])
for (k, v) in dict
updateValue(v, forKey: k)
【问题讨论】:
可能不相关,但您应该考虑将大部分逻辑移至单独的类(视图模型),而不是在视图中执行所有操作。关注点分离。 您可能还想考虑使用 SwiftyJSON:github.com/SwiftyJSON/SwiftyJSON,它更容易使用。 请解释为什么“in swift UI”很重要。我强烈建议您将创建 JSON 的尝试转移到单独的函数中。 JSON 应该只用于传输或存储/加载数据。 Tromgy:无需使用第三方库,Swift 可以非常轻松地处理 JSON。 为什么要创建json?创建后你想用它做什么? 【参考方案1】:好的......我们这里遇到的问题不是专门来自 SwiftUI,而是代码背后根本没有任何设计。
让我先说我将对您的一些数据做出几个假设,因为目前很难确定它的形状。
一步一步来。
数据建模
你当前的数据模型是
var data: [String: Any] = [
"nurseryData": [String : Any]()
]
在 Swift 中,我们应该尽可能避免使用Any
。事实上,您的数据在这里根本没有任何形状。
我建议添加一个新类型,例如...
struct NewNursery: Codable
let nurseryCode: String
let SSOId: String
和
struct SelectedNurseries: Codable
let nurseries: [NewNursery] = []
使用Codable
将让您然后使用...
let jsonData = JSONEncdoer().encode(updloadData)
这允许您删除所有合并和[String: Any]
函数和类型。
查看模型
我们还可以将视图中的一些复杂性打包到视图模型中。您似乎还有很多潜在危险的强制展开。如果你曾经强行打开一个 nil 的东西,你的应用程序就会崩溃。如果您知道它永远不会为零,那么它首先不应该在您的数据中是可选的。
让我们创建一个包含一些逻辑的视图模型...
作为快速的旁注。调用 Data
并不能真正提供关于其中内容的任何线索。
struct AddNurseryViewModel
let models: AddNurseryModels.Data // I'm really not sure what this is but I'll keep the same name you use.
var nameSuffix: String
if let isUrban = models.isUrban,
isUrban != 0
return "U"
else
return "R"
var isActiveForGgay: Bool
if let isActive = models.isActiveForGGAY,
isActive != 0
return true
else
return false
var ggayText: String
if isActiveForGgay
return "Is Active For GGAY : Yes"
else
return "Is Active For GGAY : No"
用新数据查看视图
我真的不能 100% 确定为什么会有这么多 get...
函数?我猜我会说你可能来自 Java 背景?
无论如何...让我们看看现在我们有一个模型重写视图。我还将使用一些更简洁的语法来实现你正在做的一些事情。
struct AddNurseryCard: View
@State private var checked = false
let viewModel: AddNurseryViewModel
var selectedNurseries = SelectedNurseries()
var body: some View
HStack
Image("nursery")
Divider()
VStack
Text("\(models.nurseryName!) \(viewModel.nameSuffix)")
Text(models.rANGE_NAME!)
Text(viewModel.ggayText)
CheckBoxView(checked: $checked)
.onAppear() checked = viewModel.isActiveForGgay
.onChange(of: checked) value in
nurserySelected()
Divider()
func nurserySelected()
if(checked)
// I'm really struggling to understand some of this but you need to apply my same thoughts of data modelling here.
// I will write the code as it "should" be but you will need to model it for this to work.
let profile = UserDefaults.standard.value(forKey: "profile")
let ssoId = profile.ssoid // don't use [String: Any] for things like this
let nurseryCode = models.nurseryCode!
var newNursery = NewNursery(nurseryCode: nurseryCode, ssoId: ssoId)
selectedNurseries.nurseries.append(newNursery)
addNursery(nursery: newNursery)
// This whole function should really be in a separate file. It's nothing to do with the view.
func addNursery(nursery: NewNursery)
let url = Constants.init().devUrl + Api.init().addNursery
let headers : HTTPHeaders = HTTPHeaders(["ApiKey" : Constants.init().apiKey])
AF.request(url,method: .post,parameters: nursery, encoding:JSONEncoding.default, headers: headers).responseJSON response in
switch response.result
case .failure(let error):
print(error)
case .success(let json):
print(json)
尝试以适合您正在做的事情的方式对数据进行建模确实值得。
不花时间像这样对数据进行建模会导致代码复杂且可读性/可维护性不强。
此答案中的代码并不是编写此视图的唯一方法,还有其他方法可以使它变得更好、更简洁、更优雅。
这只是初步了解如何开始改进已有的东西。
【讨论】:
以上是关于在 swift ui 中创建 Json 数组的主要内容,如果未能解决你的问题,请参考以下文章