2017-09-24 4 views
0

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의 객체를 인코딩하려고 것을 생각하지만, 배열 유형 [타일]입니다. 그러나 나는 이것을 어떻게 풀어야할지 모른다. 모든 타일 클래스를 하나의 데이터 객체로 인코딩해야합니다. 나중에는 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

당신 말이 맞습니다. 놀이터에서 작동하며 타일과 ConsumptionTile 하위 클래스가 같은 파일에 있으면 내 앱에서 작동한다는 것을 알 수 있습니다. 파일이 서로 다른 경우 BAD_ACCESS 오류가 다시 나타납니다. (파일) private이어야하며 클래스에 의해 자동으로 구현되는 메소드가 있어야합니다 (예 : 기본 init과 같음). 나는 그것을 찾아 내려고 노력했다 ... – Fabian

+0

흠, 흥미 롭다. 나는 그것을 보게 될 것이다. –

+2

정말로 문제 였다면 확실하지 않다. 그러나 나는 encode (to : Encoder) 함수를 구현했다. 코드 가능 프로토콜 및 작동했습니다. – Fabian