FileStorageKey
A type defining a file persistence strategy
final class FileStorageKey<Value> where Value : Sendable
Use fileStorage(_:decoder:encoder:)
to create values of this type.
A SharedKey
conformance that persists complex pieces of data to the file system. It works with any kind of type that can be serialized to bytes, including all Codable
types. It can be used with Shared
by providing the fileStorage(_:decoder:encoder:)
value and specifying a default:
extension URL {
static let users = URL(/* ... */)
}
@Shared(.fileStorage(.users)) var users: [User] = []
Any changes made to this value will be automatically synchronized to the URL on disk provided. Further, any change made to the file stored at the URL will also be immediately played back to the @Shared
value, as this test proves:
@Test(.dependency(\.defaultFileStorage, .fileSystem))
func externalWrite() throws {
let url = URL.temporaryDirectory.appending(component: "is-on.json")
try? FileManager.default.removeItem(at: url)
@Shared(.fileStorage(url)) var isOn = true
#expect(isOn == true)
try Data("false".utf8).write(to: url)
#expect(isOn == false)
}
Default file storage
When running your app in a simulator or device, fileStorage
will use the actual file system for saving and loading data. However, in tests and previews fileStorage
uses an in-memory, virtual file system. This makes it possible for previews and tests to operate in their own sandboxed environment so that changes made to files do not spill over to other previews or tests, or the simulator. It also allows your tests to pass deterministically and for tests to be run in parallel.
If you really do want to use the live file system in your previews, you can use prepareDependencies
:
#Preview {
let _ = prepareDependencies { $0.defaultFileStorage = .fileSystem }
// ...
}
And if you want to use the live file system in your tests you can use the dependency
test trait:
@Test(.dependency(\.defaultFileStorage, .fileSystem))
func basics() {
// ...
}
Storing a value
static func fileStorage<Value>(URL, decoder: JSONDecoder?, encoder: JSONEncoder?
) -> Self Creates a shared key that can read and write to a
Codable
value in the file system.static func fileStorage<Value>(URL, decode: @escaping (Data) throws -> Value, encode: @escaping (Value) throws -> Data
) -> Self Creates a shared key that can read and write to a value in the file system.
Overriding storage
var defaultFileStorage: FileStorage
Default file storage used by
fileStorage(_:decoder:encoder:)
.struct FileStorage
A type that encapsulates saving and loading data from disk.