2017-09-24 13 views
0

Swiftアプリケーションのオブジェクトをエンコードしてデコードする必要があります。私は以下の2つのクラスを持っています。Swift:JSONEcoder EXC_BAD_ACCESS

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 
     } 
    } 
} 

ここではコードをどのようにオブジェクトをエンコードしようとしています。

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) 

私はこの問題は、[タイル]私はサブクラスConsumptionTileのオブジェクトをエンコードしようが、配列はタイプであること、だと思います。しかし、私はこれを解決する方法を知らない。すべてのタイルクラスを1つのデータオブジェクトにエンコードする必要があります。後で、ConsumptionTileだけでなく、より多くのサブクラスが存在します。

私は、実行時に取得エラーメッセージスレッド1としてみてくださいjsonEncoder.encode(defaultTiles)ライン上だけでブレークポイントである:EXC_BAD_ACCESS(コード= 1、アドレス= 0x8の)

私は、誰かが助けることができると思います。ありがとうございました!

答えて

0

私は遊び場で試してみましたが、エラーを再現できませんでした。唯一の潜在的な問題は、encode-decodeプロセスを介してタイプ情報が失われたことです。ConsumptionTileTileとしてデコードされます。

これをプレイグラウンドに配置して実行しようとすると、自分自身が表示されます。

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)") 
} 
+0

あなたは正しいです。それは、プレイグラウンドで動作し、私はそれが私のアプリでは、TileとConsumptionTileサブクラスが同じファイル内にある場合、それを把握します。それらが異なるファイルにある場合は、BAD_ACCESSエラーが再度表示されます。 (ファイル)プライベートであり、クラスによって自動的に実装されるメソッドがなければなりません(デフォルトのinitのように)。私はそれを把握しようとしています... – Fabian

+0

hm、面白い..私はそれを見てみましょう –

+2

本当に問題があったのかどうかわかりませんが、私はエンコードを実装しました。コーディング可能なプロトコルとそれは働いた。 – Fabian