问题
I want to encode and decode some objects in my Swift app. I have the following 2 classes.
enum TileSize : Int, Codable
{
case smallTile = 3
case mediumTile = 2
case largeTile = 1
}
class Tile: NSObject, Codable
{
var tileSize: TileSize = .smallTile
var imageName: String = "";
var isDragged = false
private enum CodingKeys : String, CodingKey
{
case tileSize
case imageName
}
}
class ConsumptionTile: Tile
{
override var imageName: String
{
get
{
return "consumption"
}
set
{
super.imageName = newValue
}
}
}
And here is the code, how I try to encode the objects.
var defaultTiles : [Tile] = []
defaultTiles.append(ConsumptionTile(tileSize: .largeTile))
defaultTiles.append(Tile(tileSize: .largeTile, imageName: "my-devices"))
defaultTiles.append(Tile(tileSize: .mediumTile, imageName: "live-verbrauch"))
defaultTiles.append(Tile(tileSize: .smallTile, imageName: "zaehlerstand"))
defaultTiles.append(Tile(tileSize: .smallTile, imageName: "vertrag"))
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(defaultTiles)
I think the problem is, that I try to encode an object of the subclass ConsumptionTile but the Array is of type [Tile]. But I don't know how to solve this. I have to to encode all Tile-classes to one data object. Later there will be more subclasses and not just the ConsumptionTile.
The error I get on runtime is just a breakpoint on the try jsonEncoder.encode(defaultTiles) line with the message Thread 1: EXC_BAD_ACCESS (code=1, address=0x8)
I hope someone can help. Thank you!
回答1:
I just tried it in the playground, and I wasn't able to reproduce the error. The only potential problem was the loss of the type information through the encode
- decode
process, where the ConsumptionTile
is decoded as a Tile
.
If you put this to the playgrounds and try to run it, you'll see yourself.
import Foundation
enum TileSize : Int, Codable
{
case smallTile = 3
case mediumTile = 2
case largeTile = 1
}
class Tile: NSObject, Codable
{
var tileSize: TileSize = .smallTile
var imageName: String = "";
var isDragged = false
init(tileSize: TileSize, imageName: String) {
self.tileSize = tileSize
self.imageName = imageName
}
private enum CodingKeys : String, CodingKey
{
case tileSize
case imageName
}
}
class ConsumptionTile: Tile
{
init(tileSize: TileSize) {
super.init(tileSize: tileSize, imageName: "")
}
required init(from decoder: Decoder) throws {
fatalError("init(from:) has not been implemented")
}
override var imageName: String
{
get
{
return "consumption"
}
set
{
super.imageName = newValue
}
}
}
var defaultTiles : [Tile] = []
defaultTiles.append(ConsumptionTile(tileSize: .largeTile))
defaultTiles.append(Tile(tileSize: .largeTile, imageName: "my-devices"))
defaultTiles.append(Tile(tileSize: .mediumTile, imageName: "live-verbrauch"))
defaultTiles.append(Tile(tileSize: .smallTile, imageName: "zaehlerstand"))
defaultTiles.append(Tile(tileSize: .smallTile, imageName: "vertrag"))
let jsonEncoder = JSONEncoder()
let jsonData = try! jsonEncoder.encode(defaultTiles)
let out = try! JSONDecoder().decode([Tile].self, from: jsonData)
for tile in out {
print(">>> \(tile.imageName)")
}
来源:https://stackoverflow.com/questions/46388867/swift-jsonecoder-exc-bad-access