here is the declaration for recipe:
struct recipe: Codable, Identifiable, Hashable {
private let imageName : String
struct step: Codable, Identifiable, Hashable {
var id: Int
var isDone: Bool
var text : String
static let `default` = step(id: 00, isDone: false, text: "default step")
}
struct ingredient: Hashable, Identifiable, Codable {
var id: Int
var hasIt: Bool
let quantity : Double
let mesurment : String
let name : String
static let `default` = ingredient(id: 00, hasIt: false, quantity: 1, mesurment: "cup", name: "default")
}
var id: Int
var Name : String
var image: Image{
Image(imageName)
}
var description : String
var steps : [step]
var ingredients : [ingredient]
var notes: String
var link: String
static let `default` = recipe(imageName: "image", id: 00, Name: "default", description: "enter des.", steps: [step(id: 00, isDone: false, text: "step1"), step(id: 01, isDone: false, text: "step 2")], ingredients: [ingredient(id: 00, hasIt: false, quantity: 10.0, mesurment: "cup", name: "ing. 1")], notes: "notes", link: "google.com")
}
then i define my array of recipes from a json file:
@Published var recipes: [recipe] = load("data.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)")
}
}
after that i have some other files that pass down the recipe to the file:
@Binding var Recipe: recipe
var body: some View {
List {
HStack {
Text("name")
Divider()
TextField("name", text: $Recipe.Name)
}
ZStack(alignment: .leading) {
Text("description ")
.font(.system(.body))
.foregroundColor(.clear)
.padding(14)
TextEditor(text: $Recipe.description)
.font(.system(.body))
.frame(height: max(60, 200))
.cornerRadius(10.0)
.shadow(radius: 1.0)
}
VStack{
Button("add") {
Recipe.steps.append(recipe.step.default.self)
//test()
}
/*ForEach($Recipe.steps, id: \.self) { $Step in
TextField(String(Step.id), text: $Step.text)
Text(" ")
}*/
ForEach($Recipe.steps){$step in
TextField(String($step.id), text: $step.text)
Text(" ")
}
}
}
}
}
struct editView_Previews: PreviewProvider {
static var previews: some View {
editView(Recipe: .constant(recipe.default))
}
}
I'm making this app parallel to the Landmarks app tutorial and the structure is very similar.
as you can see i tested with the id declaration but it has a wired behaviour to unselect the text in the textfield after I edit a character
any idea why adding the id thing would do that?
anyway it fixed the problem
thanks for the fat answers
sam
btw is there a way to upload a project or do I need to pass by a git hub like site?
sorry for my very limited knowledge; I am still learning swiftUI
Post
Replies
Boosts
Views
Activity
are you talking about a .sheet(...) view?
sorry for the short answer yesterday
here is the example implementation:
struct ShowLicenseAgreement: View {
@State private var isShowingSheet = false
var body: some View {
Button(action: {
isShowingSheet.toggle()
}) {
Text("Show License Agreement")
}
.sheet(isPresented: $isShowingSheet,
onDismiss: didDismiss) {
VStack {
Text("License Agreement")
.font(.title)
.padding(50)
Text("""
Terms and conditions go here.
""")
.padding(50)
Button("Dismiss",
action: { isShowingSheet.toggle() })
}
}
}
func didDismiss() {
// Handle the dismissing action.
}
}
the init requires an isPresented: Binding<Bool> and a content: View parameter
(most people use brackets {} for the content)
there is another init that uses an item set to nil and the sheet shows when the item isn't nil
I hope this can help you if you want more info here is the SwiftUI sheet view developer doc
I think what you are searching a generic parameter (learn about them here: https://www.youtube.com/watch?v=a3AH0ItFTKU.
here is an example a bit like what you are doing:
struct struct1: Codable, Identifiable {
var id = UUID()
var name: String
}
struct struct2: Codable, Identifiable {
var id = UUID()
var Number: Int
}
struct SuperStruct<T: Codable>: Codable, Identifiable {
var id = UUID()
var something: T
}
var Object: SuperStruct = SuperStruct(something: struct1(name: "Hello"))
var ObjectAgain: SuperStruct = SuperStruct(something: struct2(Number: 2))
I hope this helps you,
Sam
For the static property problem :
struct struct1: Codable, Identifiable {
var id = UUID()
var name: String
}
struct struct2: Codable, Identifiable {
var id = UUID()
var Number: Int
}
struct SuperStruct<T: Codable & Identifiable>: Codable, Identifiable {
var id = UUID()
var something: T
}
extension SuperStruct where T == struct1 {
static let test1 = SuperStruct(something: struct1(name: ""))
}
extension SuperStruct where T == struct2 {
static let test2 = SuperStruct(something: struct2(Number: 10))
}
class master {
let parameterOne = SuperStruct.test1
var parameterTwo = SuperStruct(something: struct2(Number: 100))
static let def = SuperStruct(something: struct1(name: "default"))
}
what it does is it adds an extension for each structs that you want to add as static property so inside extension SuperStruct where T == struct1 the only type that T can have is struct1, if you do this you can use a static property in the extension then access it with SuperStruct.test1 or SuperStruct.test2
for the as! T thing I don't think it's an issue as you do not have an optional so you should not have any problems as you can always unwrap it with !. I'm not sure why it's asking for the as!, it doesn't always ask me so...?
Hi @kocaman,
I'm not sure I understand what you want to do, could you provide more details please?
The only thing I can see is that you put the HStack inside of the ForEach, which leads to the creation of different HStack for each button option instance.