MiddleCodeCommonNot answered yet
Convert a lock-protected shared cache class into an actor
The cache below serializes access with an NSLock. Convert it into an actor and describe what changes at every call site.
Requirements:
- Remove the manual locking; rely on actor isolation instead.
- Keep one shared instance with the same
value(for:)/store(_:for:)API. - State what callers must change and what capability is lost.
final class ImageCache {
private var storage: [String: Data] = [:]
private let lock = NSLock()
func value(for key: String) -> Data? {
lock.lock(); defer { lock.unlock() }
return storage[key]
}
func store(_ data: Data, for key: String) {
lock.lock(); defer { lock.unlock() }
storage[key] = data
}
}
Write the actor version.
Make the type an actor and delete the NSLock — the compiler now serializes access. Every call site becomes async, so callers must await the cache. You lose synchronous access: non-async code can't read the cache inline without a Task.
- ✗Assuming call sites stay synchronous after switching to an
actor - ✗Keeping the
NSLockinside the actor as if it were still needed - ✗Thinking an
actorturns the cache into a value type
- →How do you read the actor's cache from a synchronous UIKit callback?
- →Why does the compiler make every external cache read
await?
Replace class with actor and drop the NSLock — the actor serializes access itself:
actor ImageCache {
private var storage: [String: Data] = [:]
func value(for key: String) -> Data? { storage[key] }
func store(_ data: Data, for key: String) { storage[key] = data }
}
// call site
let data = await cache.value(for: key)
await cache.store(bytes, for: key)
Every call is now async and needs await from an async context. Synchronous access is gone: from an ordinary method you must wrap the access in Task { await ... }.