arraysswiftswiftuistruct

Binding/Pass-By-Reference for Array from Struct to Struct


I have one struct, struct DropletsView: View {} which has the following array: @State private var savedQuotes: [Quote] = [] (Quote is defined elsewhere, as a custom type for my app).

I would like to pass in this savedQuotes array to another struct (struct SingleQuoteView: View{}), such that I can modify the array from within SingleQuoteView.

I was trying to pass this in by reference, like you might do in C++, but ran into many issues along the way. Now, I would appreciate direction in trying to implement @Binding for this array within SingleQuoteView.

I'm declaring it as such: SingleQuoteView(quote: quote) because of its constructor being this as of now:

init(quote: Quote) {
    self.quote = quote
    self._isBookmarked = State(initialValue: isQuoteBookmarked(quote))
    self._isLiked = State(initialValue: isQuoteLiked(quote))
}

I'm assuming I have to create a variable with the same type in SingleQuoteView, as such:

@Binding private var savedQuotes: [Quote]
    
init(quote: Quote, savedQuotesArg: Binding<[Quote]>) {
    self.quote = quote
    self._isBookmarked = State(initialValue: isQuoteBookmarked(quote))
    self._isLiked = State(initialValue: isQuoteLiked(quote))
    self._savedQuotes = savedQuotesArg
}

And declare that struct as such: SingleQuoteView(quote: quote, savedQuotesArg: $savedQuotes).

However, this gives the following error within the constructor (init()): Variable 'self.savedQuotes' used before being initialized

My goal is to modify the savedQuotes state var in DropletsView as such, inside of one of SingleQuoteView's functions:

private func toggleBookmark() {
    isBookmarked.toggle()
    
    var bookmarkedQuotes = getBookmarkedQuotes()
    if isBookmarked {
        bookmarkedQuotes.append(quote)
    } else {
        bookmarkedQuotes.removeAll { $0.id == quote.id }
        
        // ------------------ line I want to add: ----------------
        savedQuotes.removeAll { $0.id == quote.id }
        // ------------------ line I want to add^^ ----------------
    }
    saveBookmarkedQuotes(bookmarkedQuotes)
    
    interactionsIncrease()
}


Solution

  • Following feedback from the comments, I've made the following changes to very simply fix this issue with binding savedQuotes between these two structs.

    Passed in savedQuotes from DropletsView to SingleQuoteView as such: SingleQuoteView(quote: quote, savedQuotes: $savedQuotes)

    Created this binding inside of SingleQuoteView: Binding var savedQuotes: [Quote]

    Removed the init() method entirely.

    Then, I added the exact line I wanted to here:

    private func toggleBookmark() {
        isBookmarked.toggle()
        
        var bookmarkedQuotes = getBookmarkedQuotes()
        if isBookmarked {
            bookmarkedQuotes.append(quote)
        } else {
            bookmarkedQuotes.removeAll { $0.id == quote.id }
            savedQuotes.removeAll { $0.id == quote.id }
        }
        saveBookmarkedQuotes(bookmarkedQuotes)
        
        interactionsIncrease()
    }
    

    Thanks for the feedback in the comments.