カスタムデータ型をに格納しようとしていAppStorage
ます。これを行うには、モデルはに準拠しますRawRepresentable
(このチュートリアルに従います)。正常に動作していますが、@AppStorage
変数を初期化するときに初期UserModel
値が必要です。変数をオプションにしたいので、ユーザーがサインアウトしている場合はnilにすることができます。これは可能ですか?
クラス/ビュー内で、次のように初期化できます。
@AppStorage("user_model") private(set) var user: UserModel = UserModel(id: "", name: "", email: "")
しかし、私はこのように初期化したい:
@AppStorage("user_model") private(set) var user: UserModel?
モデル:
struct UserModel: Codable {
let id: String
let name: String
let email: String
enum CodingKeys: String, CodingKey {
case id
case name
case email
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
do {
id = try String(values.decode(Int.self, forKey: .id))
} catch DecodingError.typeMismatch {
id = try String(values.decode(String.self, forKey: .id))
}
self.name = try values.decode(String.self, forKey: .name)
self.email = try values.decode(String.self, forKey: .email)
}
init(id: String, name: String, email: String) {
self.id = id
self.name = name
self.email = email
}
}
// MARK: RAW REPRESENTABLE
extension UserModel: RawRepresentable {
// RawRepresentable allows a UserModel to be store in AppStorage directly.
public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8),
let result = try? JSONDecoder().decode(UserModel.self, from: data)
else {
return nil
}
self = result
}
var rawValue: String {
guard let data = try? JSONEncoder().encode(self),
let result = String(data: data, encoding: .utf8)
else {
return "[]"
}
return result
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(email, forKey: .email)
}
}
以下のコードは、適合性を追加したために機能しますUserModel: RawRepresentable
。
@AppStorage("user_model") private(set) var user: UserModel = UserModel(id: "", name: "", email: "")
UserModel?
以下を機能させたい場合は、同じことを行う必要があります。
@AppStorage("user_model") private(set) var user: UserModel? = nil
考えられる解決策は次のとおりです。
extension Optional: RawRepresentable where Wrapped == UserModel {
public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8),
let result = try? JSONDecoder().decode(UserModel.self, from: data)
else {
return nil
}
self = result
}
public var rawValue: String {
guard let data = try? JSONEncoder().encode(self),
let result = String(data: data, encoding: .utf8)
else {
return "[]"
}
return result
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: UserModel.CodingKeys.self)
try container.encode(self?.id, forKey: .id)
try container.encode(self?.name, forKey: .name)
try container.encode(self?.email, forKey: .email)
}
}
注:私はあなたがすでに持っていた実装を再利用しましたUserModel: RawRepresentable
-この場合、いくつかの修正が必要になるかもしれません。
また、準拠Optional: RawRepresentable
しているため、UserModel
公開する必要もあります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加