Hiro
Hiro

Reputation: 165

【SwiftUI】How to initialize an empty struct

I need some kind help in SwiftUI.

I have a model below that takes in JSON data. When I want to initialize it as an empty array, it should be simple, just stating Answers, but how can I initialize it not as an array but an empty single data set.

struct Answers: Identifiable, Decodable  {
    let id: Int
    let questionsUsersId: Int
    let reactions: [Reactions]

enum CodingKeys: String, CodingKey {
        case id = "questions_id"
        case questionsUsersId = "questions_users_id"
        case reactions = "reactions"
    }

init(from decoder: Decoder) throws {

    let container = try decoder.container(keyedBy: CodingKeys.self)

    self.id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0
    self.questionsUsersId = try container.decodeIfPresent(Int.self, forKey: .questionsUsersId) ?? 0
    self.reactions = try container.decodeIfPresent([Reactions].self, forKey: .reactions) ?? [Reactions]()
}


 }

I've tried var answer: Answers = Answers( ) but got the errors below:

//Missing argument for parameter 'from' in call
//Insert 'from: <#Decoder#>'

The reason I want to initialize it empty is because I need to hand over the default value of it when the data model is nil. (i.e. what should I write in the xxx?)

 @ObservedObject var receiveAnswersViewModel = ReceiveAnswersViewModel()
  //abbreviate
            NavigationLink(destination: AnswerDetailView(answer: receiveAnswersViewModel.answer ?? xxx), isActive: $shouldNavigate) {
                    
                        ForEach(myPageViewModel.answers(forFilter: selectedFilter)?.answers ?? [Answers]()) { answer in
                         
                         AnswerCell(answer: answer)
                                .gesture(TapGesture()
                                                .onEnded({ _ in
                                                    //your action here
                                    self.answersId = answer.answersId
                                    receiveAnswersViewModel.fetchAnswers(answers_id: answersId ?? 0)
                                       }))
                         }
                    }

This is what I'm trying to do above: Show several cells using NavigationLink. (Imagine that the cells are tweets.) Press one of the tweets in the list → Call fetchAnswers func in the View Model which takes the pressed tweet id as the argument → Returns the specific tweet detail info→ Put it in the Answer model → Hand it over to the View → Navigate to the Tweet Detail View.

View Model code is below:

class ReceiveAnswersViewModel: ObservableObject {
@Published var answer: Answers?

func fetchAnswers(answers_id: Int){
//abbreviate
self.answer = try JSONDecoder().decode(Answers.self, from: data)
}

Thanks in advance.

Upvotes: -1

Views: 2205

Answers (1)

vadian
vadian

Reputation: 285039

A reasonable way is to add a static method to create an empty instance. In this case you have also to add the init method

By the way name the struct in singular form, an instance represents likely one Answer

struct Answer: Identifiable, Decodable  {
    let id: Int
    let questionsUsersId: Int
    let reactions: [Reactions]

    static let example = Answer(id: 0, questionsUsersId: 0, reactions: [])

    init(id: Int, questionsUsersId: Int, reactions: [Reactions]) {
        self.id = id
        self.questionsUsersId = questionsUsersId
        self.reactions = reactions
    }

...

Then you can declare

var answer = Answer.example 

Upvotes: 1

Related Questions