Swift 传递具有包装属性的对象don';不允许在(集合)上编译

Swift 传递具有包装属性的对象don';不允许在(集合)上编译,swift,xcode,nsuserdefaults,property-wrapper,Swift,Xcode,Nsuserdefaults,Property Wrapper,我遵循以下指南使用用户默认值创建包装属性: 现在,我有了LocalStorage类,它将在本教程结束时接受这个“Storage()”类,然后访问该对象的引用以从UserDefaults值获取数据。出于某种原因,当我在代码中设置字符串时,它不再生成/编译。它适用于布尔人。下面是一个例子: // The marker protocol protocol PropertyListValue {} extension Data: PropertyListValue {} extension Stri

我遵循以下指南使用用户默认值创建包装属性:

现在,我有了LocalStorage类,它将在本教程结束时接受这个“Storage()”类,然后访问该对象的引用以从UserDefaults值获取数据。出于某种原因,当我在代码中设置字符串时,它不再生成/编译。它适用于布尔人。下面是一个例子:

// The marker protocol
protocol PropertyListValue {}

extension Data: PropertyListValue {}
extension String: PropertyListValue {}
extension Date: PropertyListValue {}
extension Bool: PropertyListValue {}
extension Int: PropertyListValue {}
extension Double: PropertyListValue {}
extension Float: PropertyListValue {}

// Every element must be a property-list type
extension Array: PropertyListValue where Element: PropertyListValue {}
extension Dictionary: PropertyListValue where Key == String, Value: PropertyListValue {}

struct Key: RawRepresentable {
    let rawValue: String
}

extension Key: ExpressibleByStringLiteral {
    init(stringLiteral: String) {
        rawValue = stringLiteral
    }
}

extension Key {
    static let isFirstLaunch: Key = "isFirstLaunch"
    static let username: Key = "username"
}

@propertyWrapper
struct UserDefault<T: PropertyListValue> {
    let key: Key

    var wrappedValue: T? {
        get { UserDefaults.standard.value(forKey: key.rawValue) as? T }
        set { UserDefaults.standard.set(newValue, forKey: key.rawValue) }
    }
}

struct Storage {
    @UserDefault(key: .isFirstLaunch)
    var isFirstLaunch: Bool

    @UserDefault(key: .username)
    var username: String
}

struct LocalStorage{

    var storage: Storage

    init(storage: Storage){
       self.storage = storage
    }

    func ex(){
         storage.username = "travis" // will not compile... "Abort 6" 
         storage.isFirstLaunch= true // without line above, it will compile
     }

}
//标记协议
协议PropertyListValue{}
扩展数据:PropertyListValue{}
扩展字符串:PropertyListValue{}
扩展日期:PropertyListValue{}
扩展Bool:PropertyListValue{}
扩展名Int:PropertyListValue{}
双扩展名:PropertyListValue{}
扩展浮点:PropertyListValue{}
//每个元素都必须是属性列表类型
扩展数组:PropertyListValue,其中元素:PropertyListValue{}
扩展字典:PropertyListValue,其中键==字符串,值:PropertyListValue{}
结构键:可表示{
让rawValue:字符串
}
扩展键:ExpressibleByStringLiteral{
init(stringLiteral:String){
rawValue=stringLiteral
}
}
分机键{
静态let isFirstLaunch:Key=“isFirstLaunch”
静态let username:Key=“username”
}
@房地产经纪人
结构用户默认值{
让钥匙:钥匙
var wrappedValue:T{
将{UserDefaults.standard.value(forKey:key.rawValue)获取为?T}
set{UserDefaults.standard.set(newValue,forKey:key.rawValue)}
}
}
结构存储{
@UserDefault(键:.isFirstLaunch)
var isFirstLaunch:Bool
@UserDefault(键:。用户名)
var用户名:String
}
结构本地存储{
var存储:存储
初始化(存储:存储){
self.storage=存储
}
func ex(){
storage.username=“travis”//将不编译…”中止6
storage.isFirstLaunch=true//如果上面没有行,它将编译
}
}
好的,两个变化:

struct Storage {
    @UserDefault(key: .isFirstLaunch)
    var isFirstLaunch: Bool?

    @UserDefault(key: .username)
    var username: String?
}


如果你能发布一个完全可运行的代码,那就更好了,什么是
存储
?@matt我很抱歉。。。这一切都在提供的链接中。我不想复制整篇文章……说“这都是链接”是没有意义的。链接是一篇文章。你的代码就是你的代码。我们需要知道你在做什么,而不是一些文章说什么。你可能从一篇文章中得出错误的结论。这篇文章可能是错的。重要的是你的代码。堆栈溢出当你说你的代码有问题时,你需要显示你有问题的代码。没有链接。不是其他代码。谢谢请阅读。非常感谢你发布这个问题,特拉维斯,我也有同样的问题。就是这个。非常感谢。
mutating func ex() {
    storage.username = "travis"
    storage.isFirstLaunch = true
}