首页 > 解决方案 > 如何创建对象的新实例并将其传递到数组 SwiftUI

问题描述

我想创建一个简单的程序来编辑这个 JSON:https ://pastebin.com/7jXyvi6Y 我创建了 Smoothie 结构并将冰沙读入数组。现在我想创建一个新的 Smoothie 实例,我应该将它作为参数传递给 SmoothieForm。在冰沙形式中,我应该用值完成字段,然后这个冰沙应该添加到数组中,数组应该保存在 json 中。如何创建此 Smoothie 结构的新实例?以及如何附加到数组中?

我的冰沙有结构

import Foundation
import SwiftUI

struct Smoothie : Hashable, Codable, Identifiable {
    var id: Int
    var name: String
    var category: Category
    var wasDone: Bool
    var isFavorite: Bool
    var time: String
    var ingedients: [Ingedients]
    var steps: [Steps]
    var image : Image {
        Image(imageName)
    }
    
    enum Category: String, CaseIterable, Codable {
        case forest = "Forest fruit"
        case garden = "Garden fruit"
        case egzotic = "Exotic"
        case vegatble = "Vegetables"
    }
    
    private var imageName: String
    struct Steps: Hashable, Codable {
        var id: Int
        var description: String
    }
    struct Ingedients: Hashable, Codable {
        var id: Int
        var name: String
        var quantity: Double
        var unit: String
    }
}

现在我用前几个字段构建了表单视图:

struct SmoothieForm: View {
    
   
    var body: some View {
        VStack {
        Text("Add smooth")
            HStack {
                Text("Name")
                TextField("Placeholder", text: .constant(""))
            }
            HStack {
                Text("Category")
                TextField("Placeholder", text: .constant(""))
            }
            HStack {
                Text("Time")
                TextField("Placeholder", text: .constant(""))
            }
            Divider()
            
        }
        .padding(.all)
    }
}

struct SmoothieForm_Previews: PreviewProvider {
    static var previews: some View {
        SmoothieForm()
    }
}

从 json 加载数据的类:

import Foundation

final class ModelData:ObservableObject{
    @Published var smoothies: [Smoothie] = load("smoothieData.json")
}

func load<T: Decodable>(_ filename: String) -> T {
    let data: Data
    
    guard let file = Bundle.main.url(forResource: filename,withExtension: nil) else {
        fatalError("Couldn't find \(filename) in main bundle.")
    }
    
    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
    
}

我每天都在使用 c#

标签: iosarraysswiftswiftui

解决方案


import SwiftUI
//You need default values so you can initialize an empyty item
struct Smoothie : Hashable, Codable, Identifiable {
    //Find a way to make this unique maybe switch to UUID
    var id: Int = 999999
    var name: String = ""
    var category: Category = Category.unknown
    var wasDone: Bool = false
    var isFavorite: Bool = false
    var time: String = ""
    var ingedients: [Ingedients] = []
    var steps: [Steps] = []
    var image : Image {
        if !imageName.isEmpty{
            return Image(imageName)
        }else{
            return Image(systemName: "photo")
        }
    }
    
    enum Category: String, CaseIterable, Codable {
        case forest = "Forest fruit"
        case garden = "Garden fruit"
        case egzotic = "Exotic"
        case vegatble = "Vegetables"
        case unknown
    }
    
    private var imageName: String = ""
    struct Steps: Hashable, Codable {
        var id: Int
        var description: String
    }
    struct Ingedients: Hashable, Codable {
        var id: Int
        var name: String
        var quantity: Double
        var unit: String
    }
}
struct SmothieForm: View {
    //Give the View access to the Array
    @StateObject var vm: ModelData = ModelData()
    //Your new smoothie will be an empty item
    @State var newSmoothie: Smoothie = Smoothie()
    var body: some View {
        VStack {
            Text("Add smooth")
            HStack {
                Text("Name")
                //reference the new smoothie .constant should only be used in Preview Mode
                TextField("Placeholder", text: $newSmoothie.name)
            }
            VStack {
                Text("Category")
                //reference the new smoothie .constant should only be used in Preview Mode
                Picker(selection: $newSmoothie.category, label: Text("Category"), content: {
                    ForEach(Smoothie.Category.allCases, id: \.self){ category in
                        Text(category.rawValue).tag(category)
                    }
                })
            }
            HStack {
                Text("Time")
                //reference the new smoothie .constant should only be used in Preview Mode
                TextField("Placeholder", text: $newSmoothie.time)
            }
            Divider()
            //Append to array when the user Saves
            Button("Save - \(vm.smoothies.count)", action: {
                vm.smoothies.append(newSmoothie)
            })
        }
        .padding(.all)
    }
}

推荐阅读