Considering that database storage is a good use case for property wrappers, I have made a small example that can read and write Codable
values to a location in the Firebase Realtime Database using a property wrapper.
For those who don't know this database, it can basically be thought of as a key/value tree - similar to a JSON document. And thus every value in the database can be located through a path of keys.
For the following database content:
{
"chatrooms": {
"firechat": {
"configuration": {
"name": "Fire chat"
}
}
}
}
The path /chatrooms/firechat/configuration
could be considered to point out a Configuration
entity that has a String
based name
property.
My property wrapper implementation is initialized with the path to the value in the database - and I have made this concept type safe by modelling a tree of a generic Path
type that sort of describes a schema for the database.
Referencing the Configuration
entity above can be done as follows:
@FirebaseValue(path: Path.chatrooms.child("firechat").configuration)
var configuration: Configuration = .default
This works very well when the path in question can be determined statically. If for instance I would like to create some view model that represented a specific chat room, it would be natural to let this view model be initialized with the key of that specific chat room.
E.g.:
class ViewModel {
let chatroomKey: String
@FirebaseValue(path: Path.chatrooms.child(self.chatroomKey).configuration)
var configuration: Configuration = .default
init(chatroomKey: String) {
self.chatroomKey = chatroomKey
}
}
This does not compile since I cannot refer to self.chatroomKey
before initialization. Using another tecnique than property wrappers I might have made the property lazy in order to be able to refer to the key.
When it becomes possible to create local property wrappers, I can of course do something similar to:
class ViewModel {
@FirebaseValue
var configuration: Configuration = .default
init(chatroomKey: String) {
@FirebaseValue(path: Path.chatrooms.child(chatroomKey).configuration)
var cfg: Configuration = .default
self._configuration = _cfg
}
}
Or something similar. But still it doesn't read nearly as nicely as the version where the property in the viewmodel carried the path configuration directly.
So finally my questions:
Is my use case for property wrappers bad due to the fact that I would like a dynamic element of my property wrapper initialization?
Have other similar use cases been discussed during pitch or review? I haven't been able to find any.
Is there a chance that the feature might see some aspect of lazily initializing a whole property wrapper to enable something like what I am trying to do?
Or is there some clever trick I may use to achieve what I want?