编码具有 @State 的结构
Encoding a struct that has @State
我有这样的结构
struct SymbolView: View, Identifiable {
let id = UUID()
var name:String
var code:String
@State var position = CGPoint(x:100, y:100)
@State var scale = CGFloat(1)
}
我需要使用 Codable 将其转换为 JSON,所以我这样做了
extension SymbolView: Codable{
private enum CodingKeys: String, CodingKey {
case name
case code
case position
case scale
}
public func encode(to encoder:Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
do {
try container.encode(self.name, forKey: .name)
try container.encode(self.code, forKey: .code)
try container.encode(self.position, forKey: .position)
try container.encode(self.scale, forKey: .scale)
} catch (let error) {
print(error.localizedDescription)
}
}
}
errors: 不能自动合成'Decodable' 因为'State'不符合'Decodable'和点一样的错误。
这里的问题似乎是两个属性都是 @State
。
我该如何解决?
我建议将 id、名称、代码、位置、比例封装到它们自己的可编码结构中,并将其用作 SymbolView 上的单个 @State 属性。然后,只是 encode/decode 模型而不是尝试 encode/decode 视图。
struct SymbolModel : Identifiable, Codable {
var id = UUID()
var name:String
var code:String
var position = CGPoint(x:100, y:100)
var scale = CGFloat(1)
}
struct SymbolView: View {
@State var symbol : SymbolModel
var body: some View {
Text("Symbol...")
}
func encodeSymbolModel() -> Data? {
try? JSONEncoder().encode(symbol)
}
}
struct ContentView: View {
@State var symbolModel : SymbolModel?
var body: some View {
if let symbolModel = symbolModel {
SymbolView(symbol: symbolModel)
}
}
func decodeSymbolFromData(data: Data) -> SymbolModel? {
do {
return try JSONDecoder().decode(SymbolModel.self, from: data)
} catch {
print(error)
}
return nil
}
}
或者,保留您的原始代码并编写自定义代码 init(from decoder)
:
extension SymbolView: Codable {
private enum CodingKeys: String, CodingKey {
case name
case code
case position
case scale
}
public func encode(to encoder:Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
do {
try container.encode(self.name, forKey: .name)
try container.encode(self.code, forKey: .code)
try container.encode(self.position, forKey: .position)
try container.encode(self.scale, forKey: .scale)
} catch (let error) {
print(error.localizedDescription)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
code = try values.decode(String.self, forKey: .code)
position = try values.decode(CGPoint.self, forKey: .position)
scale = try values.decode(CGFloat.self, forKey: .scale)
}
}
我有这样的结构
struct SymbolView: View, Identifiable {
let id = UUID()
var name:String
var code:String
@State var position = CGPoint(x:100, y:100)
@State var scale = CGFloat(1)
}
我需要使用 Codable 将其转换为 JSON,所以我这样做了
extension SymbolView: Codable{
private enum CodingKeys: String, CodingKey {
case name
case code
case position
case scale
}
public func encode(to encoder:Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
do {
try container.encode(self.name, forKey: .name)
try container.encode(self.code, forKey: .code)
try container.encode(self.position, forKey: .position)
try container.encode(self.scale, forKey: .scale)
} catch (let error) {
print(error.localizedDescription)
}
}
}
errors: 不能自动合成'Decodable' 因为'State'不符合'Decodable'和点一样的错误。
这里的问题似乎是两个属性都是 @State
。
我该如何解决?
我建议将 id、名称、代码、位置、比例封装到它们自己的可编码结构中,并将其用作 SymbolView 上的单个 @State 属性。然后,只是 encode/decode 模型而不是尝试 encode/decode 视图。
struct SymbolModel : Identifiable, Codable {
var id = UUID()
var name:String
var code:String
var position = CGPoint(x:100, y:100)
var scale = CGFloat(1)
}
struct SymbolView: View {
@State var symbol : SymbolModel
var body: some View {
Text("Symbol...")
}
func encodeSymbolModel() -> Data? {
try? JSONEncoder().encode(symbol)
}
}
struct ContentView: View {
@State var symbolModel : SymbolModel?
var body: some View {
if let symbolModel = symbolModel {
SymbolView(symbol: symbolModel)
}
}
func decodeSymbolFromData(data: Data) -> SymbolModel? {
do {
return try JSONDecoder().decode(SymbolModel.self, from: data)
} catch {
print(error)
}
return nil
}
}
或者,保留您的原始代码并编写自定义代码 init(from decoder)
:
extension SymbolView: Codable {
private enum CodingKeys: String, CodingKey {
case name
case code
case position
case scale
}
public func encode(to encoder:Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
do {
try container.encode(self.name, forKey: .name)
try container.encode(self.code, forKey: .code)
try container.encode(self.position, forKey: .position)
try container.encode(self.scale, forKey: .scale)
} catch (let error) {
print(error.localizedDescription)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
code = try values.decode(String.self, forKey: .code)
position = try values.decode(CGPoint.self, forKey: .position)
scale = try values.decode(CGFloat.self, forKey: .scale)
}
}