在 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 数组的主要内容,如果未能解决你的问题,请参考以下文章

在 swift alamofire 中创建 json 数组

如何在 swift 中创建新闻提要 UI

如何在 ios swift 中创建 json 对象

在 Swift-Json 中创建 NSMutableDictionary

在 Swift 中创建一个随机数数组

如何在 Swift 中创建 UITextField 对象数组?