On the simulator I was noticing some lag, but it runs fine. I finished the feature and went to run it on my phone and it crashes saying:
Message from debugger: Terminated due to memory issue
I do have zombie objects turned off in the Schema (as I was reading it can give problems)
Doing some debugging I found the issue happens after I assigned the JSON downloaded from the api, so maybe the object is not being released? This is the first time I face something like this. Here's how the api request looks:
let fetchWalletBalances = Task(priority: .high) {
try await fetchTokenBalances(user: user, userWallets: userWallets, verifiedTokensDictionary: verifiedTokensDictionary)
}
let tokensPlusCoinGeckoIds = try await fetchWalletBalances.value
At this point the memory shows on XCode like 1Gb already
then I assign it to do further calculations (all in my view model):
let walletsTokenData: OrderedDictionary<String, [TokenBalanceClassAModel]> = tokensPlusCoinGeckoIds.walletsTokenData
and here it crashes.
How can I release some memory or go about this issue?
EDIT:
After lots of debugging and trying some of the tools suggested by @Alexander, I found that the memory leak happens in the block below, it jumps from 33 Mb to 1.76 GB (I'm using Alamofire to do the api fetch):
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
}
}
}
}
The memory jumps at line: AF.request(url, method: .get, requestModifier: { $0.timeoutInterval = .infinity }).validate(statusCode: 200..<600).responseData { response in
The problem is that on every loop (see below) it keeps adding the memory from the previous iteration, so it's never clear.
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!)")
}
}
}
What's happening there and how can I fix it?