skip to Main Content

I have two quote dictionaries I’m trying to append after an in-app purchase. I have tried several different methods to append the dictionaries together but I’m still getting an error "No exact matches in call to instance method ‘append’"

I have established variables for each array to then append the array within the struct.

Any thoughts? Is there a better method I should use to add the quotes from the array called QuoteDetails2 to the initial array QuoteDetails?

var topQuotes = [QuoteDetails]()
var additionalQuotes = [QuoteDetails2]()

public struct QuoteProvider {
    static func all() -> [QuoteDetails] {
        [
            QuoteDetails(
                id: "1",
                texts: "High school is fun",
                authors:  "SM"
            ),
            QuoteDetails(
                id: "2",
                texts: "Middle School is fun",
                authors:  "A. Philip Randolph"
            ),
            QuoteDetails(
                id: "3",
                texts: "The playground is fun",
                authors:  "Booker T. Washington"
            ),
            QuoteDetails(
                id: "4",
                texts: "Hold on to your dreams of a better life and stay committed to striving to realize it.",
                authors:  "KJ"
            )
        ]
    }
    static func all2() -> [QuoteDetails2] {
        [ 
            QuoteDetails2(
                id: "1",
                texts: "The cat ran fast",
                authors: " ME"
            ),
            QuoteDetails2(
                id: "2",
                texts: "The dog ran fast.",
                authors: " ME"           
            ),
            QuoteDetails2(
                id: "3",
                texts: "End life problems",
                authors: "ME"           
            )                
        ]
    }
    func showPremiumQuotes() {
        if UserDefaults.standard.bool(forKey: "premiumQuotes") == true {
            topQuotes.append(contentsOf: additionalQuotes)
        }
    }
    /// - Returns: A random  item.
    static func random() -> QuoteDetails {
          let allQuotes = QuoteProvider.all()
          let randomIndex = Int.random(in: 0..<allQuotes.count)
          return allQuotes[randomIndex]
    }
}

3

Answers


  1. This should be a comment but it would be a bit tricky to explain what Koropok & Leo Dabus were saying without the formatting.

    You have two arrays:

    var topQuotes = [QuoteDetails]()
    var additionalQuotes = [QuoteDetails2]()
    

    When you try to do this line topQuotes.append(contentsOf: additionalQuotes), the compiler gives you the error because topQuotes is expecting a type QuoteDetails to be stored in it where as additionalQuotes says it is storing QuoteDetails2 so it is unable to append a different type to topQuotes.

    Just because they have the exact same properties, the compiler cannot tell they are the same because they are named differently. It is kind of doing something like this:

    var topQuotes = [Int]()
    var additionalQuotes = [String]()
    topQuotes.append(contentsOf: additionalQuotes)
    

    A quick fix to get this to work is to say topQuotes can store Any type, like this

    var topQuotes = [Any]()
    

    But I recommend against this, just showing you your options and if you are new, I would stay away from this for now.

    Based off of this and your QuoteProvider struct, it seems you have 2 structs which are identical:

    struct QuoteDetails
    {
        var id: String
        var texts: String
        var authors: String
    }
    
    struct QuoteDetails2
    {
        var id: String
        var texts: String
        var authors: String
    }
    

    What is the difference between QuoteDetails and QuoteDetails2 ? If nothing, then you can get rid of QuoteDetails2 and change

    var topQuotes = [QuoteDetails]()
    var additionalQuotes = [QuoteDetails2]()
    

    to

    var topQuotes = [QuoteDetails]()
    var additionalQuotes = [QuoteDetails]()
    

    Once you define a type, you can reuse that type multiple times.

    After you make the above change, I believe the errors should go away.

    Login or Signup to reply.
  2. you can have both QuoteDetails and QuoteDetails2 in same array if it’s Any

    var topQuotes = [Any]()
    topQuotes.append(contentsOf: additionalQuotes)
    

    To different QuoteDetails from QuoteDetails2 in Array of Any

    for quote in topQuotes {
        if let normalQuote = quote as? QuoteDetails {
            // do something with QuoteDetails
        } else if let premiumQuote = quote as? QuoteDetails2 {
            // do something with QuoteDetails2
        }
    }
    

    you doesn’t append a dictionary array to another dictionary array, but you are appending to array with different type

    Login or Signup to reply.
  3. If you want to have two separate arrays with the possibility to merge them you can add an init to one of the structures that takes the other struct as an argument.

    extension QuoteDetails {
        init(from details2: QuoteDetails2) {
            self.id = details2.id
            self.texts = details2.texts
            self.authors = details2.authors
        }
    } 
    

    and then add another static function that returns both arrays as a single one

    static func allQuotes() -> [QuoteDetails] {
         all() + all2().map(QuoteDetails.init)
    }
    

    Another option is to create a protocol that both structures conform to so that you can use a common array of that protocol type

    protocol Quote {
        var id: String { get }
        var texts: String { get }
        var authors: String { get }
    }
    

    and then a function that creates the array

    static func everyQuote() -> [Quote] {
        all() + all2()
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search