【问题标题】:Create Json array in swift ui在 swift ui 中创建 Json 数组
【发布时间】: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?创建后你想用它做什么?

标签: swift swiftui swiftui-list


【解决方案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)    
      }
    }      
  }
}

尝试以适合您正在做的事情的方式对数据进行建模确实值得。

不花时间像这样对数据进行建模会导致代码复杂且可读性/可维护性不强。

此答案中的代码并不是编写此视图的唯一方法,还有其他方法可以使它变得更好、更简洁、更优雅。

这只是初步了解如何开始改进已有的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多