En el simulador estaba notando algo de retraso, pero funciona bien. Terminé la función y fui a ejecutarla en mi teléfono y se bloquea diciendo:
Message from debugger: Terminated due to memory issueTengo objetos zombie desactivados en el esquema (mientras lo leía puede dar problemas)
Al depurar un poco, descubrí que el problema ocurre después de que asigné el JSON descargado de la API, ¿entonces tal vez el objeto no se está liberando? Esta es la primera vez que me enfrento a algo así. Así es como se ve la solicitud de API:
let fetchWalletBalances = Task(priority: .high) { try await fetchTokenBalances(user: user, userWallets: userWallets, verifiedTokensDictionary: verifiedTokensDictionary) } let tokensPlusCoinGeckoIds = try await fetchWalletBalances.valueEn este punto, la memoria se muestra en XCode como 1 Gb ya
luego lo asigno para hacer más cálculos (todo en mi modelo de vista):
let walletsTokenData: OrderedDictionary<String, [TokenBalanceClassAModel]> = tokensPlusCoinGeckoIds.walletsTokenDatay aquí se bloquea.
¿Cómo puedo liberar algo de memoria o solucionar este problema?
EDITAR:
Después de muchas depuraciones y de probar algunas de las herramientas sugeridas por @Alexander, descubrí que la fuga de memoria ocurre en el bloque a continuación, salta de 33 Mb a 1,76 GB (estoy usando Alamofire para buscar la API):
func afRequest(url: URL) async throws -> Data { try await withUnsafeThrowingContinuation { continuation in // If another error try lowering the request error: (statusCode: 200..<300) // timeoutInterval is in seconds AF.request(url, method: .get, requestModifier: { $0.timeoutInterval = .infinity }) .validate(statusCode: 200..<600) .responseData { response in if let data = response.data { continuation.resume(returning: data) return } if case let .failure(error) = response.result { print("🛑 Error on afRequest(): \(error)") continuation.resume(throwing: error) return } } } } La memoria salta a la línea: AF.request(url, method: .get, requestModifier: { $0.timeoutInterval = .infinity }).validate(statusCode: 200..<600).responseData { response in
El problema es que en cada ciclo (ver más abajo) sigue agregando la memoria de la iteración anterior, por lo que nunca está claro.
for chain in chains { if(chain.chain_id != nil) { // at some point here I get 1.67 GB of memory, shouldn't at the end of the loop clear that memory? let decodedData = await tokenBalancesClassAViewModel.fetchTokenBalancesData(walletAddress: wallet.address, chain: chain.chain_id!) let data: TokenBalanceClassAModel = decodedData let chainId = data.data.chain_id if(chainId == nil) { shouldCacheBalances = false deleteCachedData() print("🛑 Reloaded Chain: Nil. Balances won't be cached") } else { // Save into Single Address singleWalletData.append(data) print("🔁 Reloaded Chain: \(chainId!)") } } }¿Qué está pasando allí y cómo puedo solucionarlo?
Encontré el problema. El problema estaba en la vista con este bloque durante ScrollView :
else if(updateAPIDataViewModel.allWalletsData.walletsData.isEmpty && updateAPIDataViewModel.isTotalPortfolioBalanceBeingCalculated && !walletDataStoreHandlerViewModel.userWallets.isEmpty) { ScrollView(.horizontal, showsIndicators: false) { ForEach(walletDataStoreHandlerViewModel.userWallets) { wallet in HStack { ForEach(0..<(wallet.chainsWithBalance?.count ?? 0)) { _ in DummyWallet() .redacted(reason: .placeholder) } } } } }