Here is the code in question to provide more context
class HomeViewModel {
var pOffers = [Offer]()
var forceFetchOffers: Bool = false
@MainActor var offersTable: [String: Offer] = [:]
var handledAnnouncementIds: Set<String> = []
func fetchOffersAndUpdateCards() {
delegate?.setLoadingState(true)
Task {
await fetchCachedOffersIfNeeded()
await refreshCardsFromCachedOffers()
}
}
func fetchCachedOffersIfNeeded() async {
guard shouldFetchOffers() else { return }
pOffers = await personalization.getOffers()
forceFetchOffers = false
}
func refreshCardsFromCachedOffers() async {
let mappedCardsData = await mappedCardData(from: pOffers)
await refreshOfferCards(with: mappedCardsData)
}
func mapToOffersCardData(offer: Offer) async -> OfferCardData? {
switch offer.offerType {
case .abc:
return await hanldeAnnouncementCard(from: offer)
case .xyz:
return await addItemCardData(from: offer)
default:
return nil
}
}
@MainActor
func mappedCardData(from offers: [Offer]) async -> [OfferCardData] {
offersTable.removeAll()
handledAnnouncementIds = []
var index: Int = 0
return await offers
.asyncCompactMap {
guard var cardData = await self.mapToOffersCardData(offer: $0) else { return nil }
cardData.cardIndex = index
index += 1
offersTable[cardData.id] = $0
return cardData
}
}
func hanldeAnnouncementCard(from offer: Offer) async -> OfferCardData? {
if handledAnnouncementIds.contains(offer.itemID) {
return nil
}
handledAnnouncementIds.insert(offer.itemID)
return await announcementCardData(from: offer)
}
func announcementCardData(from offer: Offer) async -> OfferCardData? {
guard let announcement = await fetchAnnouncement(for: offer.itemID) else { return nil }
return ACardData(
......
......
}
}
func showDefaultOfferCards() {
Task {
let offers = getDefaultOfferTypes()
.map {
Offer(
offerType: $0,
offerName: Constants.defaultCardOfferName
)
}
let defaultCardsData = await mappedCardData(from: offers)
await refreshDefaultOfferCards(with: defaultCardsData)
}
}
}
public extension Sequence {
func asyncCompactMap<T>(_ transform: (Element) async -> T?) async -> [T] {
var values: [T] = []
for element in self {
guard let transformedElement = await transform(element) else { continue }
values.append(transformedElement)
}
return values
}
}
struct Offer {
let itemID: String
let offerType: OfferType
let offerName: String
init(
offerType: OfferType,
offerName: String = "",
itemID: String = "",
) {
self.offerType = offerType
self.offerName = offerName
self.itemID = itemID
}
}