You can't nest property wrappers inside of protocols, so what do you do instead? Type aliases don't seem to work.
import SwiftUI
@propertyWrapper struct ModuleName_Wrapped<Value, Storage: ModuleName_Storage> {
let wrappedValue = "🎁"
}
protocol ModuleName_Storage: DynamicProperty {
associatedtype Value
typealias Wrapped = ModuleName_Wrapped<Value, Self>
}
extension AppStorage: ModuleName_Storage { }
extension SceneStorage: ModuleName_Storage { }
struct S {
let x = AppStorage<Int>.Wrapped() // fine.
@AppStorage.Wrapped var y = … // Unknown attribute 'AppStorage.Wrapped'
}
It works fine when you put typealias inside a concrete type. Sounds like a bug... 
1 Like
brandon
(brandon)
3
This compiles for me:
@propertyWrapper struct ModuleName_Wrapped<Value, Storage: ModuleName_Storage> {
let wrappedValue = "🎁"
}
protocol ModuleName_Storage: DynamicProperty {
associatedtype Value
associatedtype Wrapped = ModuleName_Wrapped<Value, Self>
}
extension AppStorage: ModuleName_Storage { }
extension SceneStorage: ModuleName_Storage { }
struct S {
let x = AppStorage<Int>.Wrapped()
@AppStorage<Int>.Wrapped var y: String
}
1 Like
Nice!
…but how can you extend the types (AppStorage.Wrapped or SceneStorage.Wrapped) then?
brandon
(brandon)
5
Depending on what your exact goals are, you can try something like this:
@propertyWrapper struct ModuleName_Wrapped<Value, Storage: ModuleName_Storage> where Value == Storage.Value {
var storage: Storage
var wrappedValue: Value {
get { storage.wrappedValue }
set { storage.wrappedValue = newValue }
}
}
protocol ModuleName_Storage: DynamicProperty {
associatedtype Value
associatedtype Wrapped = ModuleName_Wrapped<Value, Self>
var wrappedValue: Value { get set }
}
extension AppStorage: ModuleName_Storage { }
struct S {
@AppStorage<String>.Wrapped var y: String
}
I don't have the Xcode beta installed, so I can't do much testing (other than checking if it compiles).
Play around with the generic constraints if you need to do any sort of type-conversion in the outer property wrapper.
?
I need to extend the Wrapped types.
brandon
(brandon)
7
What I meant is: Depending on what exactly you want your extended property wrapper to do (eg. type conversion, parsing, serialization, etc.), you can try something similar to the code snippet.
I've tried a few things. I'll show my best idea shortly.
The snippet doesn't look like an extension to the nested types, to me.
1 Like
https://github.com/JessyCatterwaul/SwiftUICodableStorage
Most relevant:
/// Common functionality for `…Storage.Codable`s.
/// - Note: Should be used directly, instead of being a property of those,
/// if property wrappers become `typealias`-able.
@propertyWrapper struct CodableStorage<Value: Codable> {
public extension AppStorage where Value: Swift.Codable {
/// Local `Data`-storage for `Codable`s .
/// - Warning: Not a good match for tvOS, due to severely limited local storage allowance.
@propertyWrapper struct Codable {
public var wrappedValue: Value {
get { value }
set { value = newValue }
}
@CodableStorage private var value: Value
}
}
public extension SceneStorage where Value: Swift.Codable {
/// Local `Data`-storage for `Codable`s .
/// - Warning: Not a good match for tvOS, due to severely limited local storage allowance.
@propertyWrapper struct Codable {
public var wrappedValue: Value {
get { value }
set { value = newValue }
}
@CodableStorage private var value: Value
}
}
@AppStorage.Codable("") var bool = Bool()
@SceneStorage.Codable("") var int = Int()
Agreed. Anyone know if this has been filed as such? If not I can do so...
EDIT: Filed as SR-14797
2 Likes