Closed reubn closed 4 months ago
Hi @reubn –
I took a quick look at your minimal test case, and I think that there's a bit of a mis-understanding of how the cache functions. Within your CountryDetailView
, you're attempting to create an object of type CountryDetailQuery.Data.Country
by fetching a CountryDetailQuery
via the cache. However, as you've never fetched CountryDetailQuery
before, you don't have a cache entry for that query.
As you said, you're really looking for the country
field – which is being supplied by a shared fragment CountryInfo
. You can, instead of storing CountryDetailQuery.Data.Country
, store CountryInfo
. And instead of fetching CountryDetailQuery
, you can do a read operation on the cache for a CountryInfo
.
Your fetch data function becomes something like this:
func fetchData() {
GraphQL.shared.apollo.store.withinReadTransaction { transaction in
let countryInfo = try transaction.readObject(ofType: CountryInfo.self, withKey: "Country:\(code)")
self.country = countryInfo
}
}
More important that having a fix (which may or may not work for your use-case) is understanding why what you're attempting to do fails.
Imagine, for a moment, that your CountryDataQuery
was much more complex:
query CountryDetailQuery($code: ID!) {
country(code: $code) {
...CountryInfo
population
officialLanguage
currentLeader
governmentType
# etc
}
}
At this point, there's a very clear divergence between the AllCountriesQuery.Country
and CountryDataQuery.Country
data types. Further, when we ask the cache to fetch a whole query, we must have executed that query before in the past. That's because of how queries are keyed.
For example, a CountryDetailQuery
with code AD
would be keyed as QUERY_ROOT.CountryDetailQuery(code: "AD")
, with selections you have keyed similarly (QUERY_ROOT.CountryDetailQuery(code: "AD").country(code: "AD")
. When you ask the cache to read
for a query, there is no entry in the cache that resolves to that query, as we've never executed it. At its core, returnCacheDataDontFetch
will resolve to code that's quite similar to the code I've written above for fetchData
but will instead tell the transaction to read
for the CountryDetailQuery
, not the CountryInfo
fragment.
I'm closing this issue due to inactivity. If this is still unresolved, feel free to provide more information and we can re-open this, or create a new issue.
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.
Summary
I have a very simple use case that doesn't seem to be handled by the normalised cache properly.
I have a query that returns a list of
Country
s using aCountryInfo
fragment.I then have a second query that queries for a specific
Country
, returning the same fragment.The data returned for the first query populates the cache, but is not used for the second query. Apollo returns the following error.
I have set up custom cache keys, but Apollo seems to only correctly return cached data for the same query, despite the 2 pieces of data in the cache having the same cache key. This is unexpected.
By introspecting the
SQLiteNormalizedCache
database I can see that the data from the first query is stored and keyed correctly, but this not appear to be read in the second. The test case behaves identically with theInMemoryNormalizedCache
.I can see that a similar issue was reported #842, and if this behaviour is intentional then the question is: how can I implement cache redirects to normalise identical objects across queries?
Thanks!
Minimal test case: https://github.com/reubn/apolloiOSBugTestCase
Version
1.9.0
Steps to reproduce the behavior
Minimal test case: https://github.com/reubn/apolloiOSBugTestCase
Logs
No response
Anything else?
No response