When trying to run the final project from Chapter 9 (EmojiArt) in release mode, the application crashes when scrolling in the gallery.
The crash is present when running on the simulator and when running on a real device (using Xcode 13.2.1).
Here what I can see in Xcode:
@globalActor actor ImageDatabase {
// ...
func image(_ key: String) async throws -> UIImage {
if await imageLoader.cache.keys.contains(key) { // Crash here: EXC_BAD_ACCESS
print("Cached in-memory")
return try await imageLoader.image(key)
}
// ...
By running the app with the address sanitizer I can see an error a the same line: “Use of deallocated memory”
My supposition is that the issue comes from the fact that we are accessing the cache
property in imageLoader
directly from the ImageDatabase.
I am not sure about that, as we are still accessing the property using async.
Following this idea I fixed this issue by making the cache
private and adding this method to ImageLoader
:
func contains(_ key: String) -> Bool {
return cache.keys.contains(key)
}
And I then used this method in ImageDatabase
where the crash was occurring:
@globalActor actor ImageDatabase {
// ...
func image(_ key: String) async throws -> UIImage {
if await imageLoader.contains(key) { // <- The change is here
print("Cached in-memory")
return try await imageLoader.image(key)
}
// ...
With this change there is no longer a crash.
But I am not sure to understand why there was a crash in the first place, can someone explain it to me ?
Is accessing an actor property unsafe ? is it because it came from another thread ?