nalexn / clean-architecture-swiftui

SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Access contents of lazylist

moh-abk opened this issue · comments

Awesome template for clean architecture!

I've the below combine pipeline which is the opposite of way you're handling data in this template;
In most real world scenarios;

  • data is first fetched from the web
  • then stored in the db
  • if fetching from web fails
  • load from db
func refreshCards(id: String) -> AnyPublisher<Void, Error> {
    var cards: [Card] = []
    return gateway
    .listCards(customerID: id)
    .map {
        response in
        response.cards.forEach {
            cards.append(Card(protoObject: $0)!)
        }
        return cards
    }

    .catch {
        err in
        // must return a Publisher
        repository.cards()
    }

    .flatMap {
        [repository] in
        repository.store(cards: $0) // Cannot convert value of type 'LazyList<Card>' to expected argument type '[Card]'
    }

    .eraseToAnyPublisher()
}

repository.store(cards: ) accepts an array of cards - [Card] - how can I unpack LazyList and turn it into an array?

Hey,

LazyList conforms to Sequence and RandomAccessCollection, so you can do just Array(list)

You may want to refactor your code and get rid of LazyList in the middle. The main reason for its use in the sample project was to allow for querying and converting CoreData objects to the data model used in the UI lazily for performance reasons.

Thanks for quick response @nalexn
I don't understand your last comment;

  • my dbrepository has - func cards() -> AnyPublisher<LazyList<Card>, Error>. PersistenceStore fetch always returns a LazyList

For your first comment, I updated the code to below;

func refreshCards(id: String) -> AnyPublisher<Void, Error> {
    var cards: [Card] = []
    return gateway
    .listCards(customerID: id)
    .map {
        response in
        response.cards.forEach {
            cards.append(Card(protoObject: $0)!)
        }
        return cards // Cannot convert return expression of type '[Card]' to return type 'LazyList<Card>'
    }

    .catch {
        err in
        // must return a Publisher
        repository.cards()
    }

    .flatMap {
        [repository] in
        repository.store(cards: Array($0))
    }

    .eraseToAnyPublisher()
}

But above I now get - Cannot convert return expression of type '[Card]' to return type 'LazyList<Card>'

You can convert LazyList to Array earlier so the returned container type matches in every step in the chain:

func refreshCards(id: String) -> AnyPublisher<Void, Error> {
    return gateway
    .listCards(customerID: id)
    .map { 
        response in
        return response.cards.map {
            Card(protoObject: $0)!
        }
    }
    .catch {
        err in
        // must return a Publisher
        Array(repository.cards())
    }

    .flatMap {
        [repository] in
        repository.store(cards: $0)
    }

    .eraseToAnyPublisher()
}

ended up getting rid of LazyList completely as your code snippet showed other errors and also kept tripping into - https://github.com/nalexn/clean-architecture-swiftui/blob/master/CountriesSwiftUI/Utilities/LazyList.swift#L124;

final code;

return gateway
            .listCards(customerID: id)
            .map { response in
                return response.cards.map {
                    Card(protoObject: $0)!
                }
            }
            .catch { err in
                // must return a Publisher
                repository.cards()
                
            }
            .flatMap { [repository] in
                repository.store(cards: Array($0))
            }
            .eraseToAnyPublisher()

thanks for the pointers!