質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

884閲覧

Dictionary型のNSKeyedArchiver.archivedData()を用いたシリアライズが出来ない

TakamasaIijima

総合スコア16

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/02/14 09:21

編集2019/02/15 06:44

前提・実現したいこと

CoreDataに保存するためにカスタムクラスを含むDictionaryをData型にシリアライズしたい。

発生している問題・エラーメッセージ

NSKeyedArchiver.archivedData(withRootObject: dict, requiringSecureCoding: false) //-> デグレートでSIGABRTする

該当のソースコード

PcState.swift

import Foundation class ArchivePcState : NSObject, NSCoding { public enum PcState: Int { case off=0, on=1, stanby=2, hibernate=3 } var e: PcState init(e: PcState) { self.e = e } func encode(with aCoder: NSCoder) { aCoder.encode(e.rawValue, forKey: "PcState") } required convenience init?(coder aDecoder: NSCoder) { let rawCase = aDecoder.decodeObject(forKey: "PcState") as! Int self.init(e: PcState(rawValue: rawCase)!) } }

Room.swift

class Room: NSObject,NSCoding { var PCs = Dictionary<Int, ArchivePcState.PcState>() override init() { self.PCs[1] = .on self.PCs[2] = .off self.PCs[3] = .on self.PCs[4] = .stanby } init(PCs: Dictionary<Int, ArchivePcState.PcState>) { super.init() self.PCs = PCs } func encode(with aCoder: NSCoder) { aCoder.encode(PCs, forKey: "PCs") } required init?(coder aDecoder: NSCoder) { super.init() self.PCs = (aDecoder.decodeObject(forKey: "PCs") as? [Int : ArchivePcState.PcState])! } }

main.swift

func serialize(Rooms: Room) let stateDict:[Int:ArchivePcState.PcState] = Rooms.PCs as [Int : ArchivePcState.PcState] let senddata = NSKeyedArchiver.archivedData(withRootObject: stateDict, requiringSecureCoding: false)

保存したいデータ

stateDict:[Int: PcState]をData型にしたもの

試したこと

一般的なNSCodingのためのencodeやrequired initも入れていますが、クラッシュしてしまいます.
PcStateにもcodingへの準拠が必要なのでしょうか...?

補足情報(FW/ツールのバージョンなど)

Swift 4
Xcode10.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2019/02/15 00:32

なぜDataで返ってきているものを、わざわざNSDataにキャストして、直後にDataにキャストしているのでしょうか?
fuzzball

2019/02/15 00:33

archivedData(withRootObject:) は deprecatedなので使わない方がいいです。
fuzzball

2019/02/15 07:29 編集

>>PcStateにもcodingへの準拠が必要なのでしょうか...? Codableですかね?なぜ試してみないのでしょうか?
takabosoft

2019/02/15 06:37

手元で動かしてみると var PCs = Dictionary<Int, PcState>() のPcStateが未定義だったり  CellState が未定義だったりして試せません。
TakamasaIijima

2019/02/15 06:38

すみません。すぐ修正します.(質問用にコード少し変えています)
guest

回答1

0

ベストアンサー

Dictionary<Int, ArchivePcState.PcState>をそのままNSKeyedArchiver.archivedData(withRootObject:requiringSecureCoding:)に投げると
ArchivePcState.PcState型がNSCodingプロトコルに準拠していないのでエラーがでます。

かと言ってenumNSCodingプロトコルに準拠させることができないようなので、
rawValueに変換したものをアーカイブすれば良いと思います。

例:

swift

1func serialize(Rooms: Room) { 2 let stateDict: [Int : Int] = Rooms.PCs.mapValues { $0.rawValue } 3 let senddata = try! NSKeyedArchiver.archivedData(withRootObject: stateDict, requiringSecureCoding: false) 4 print(senddata) 5}

あと余談ですが、Room型の変数名をRoomsにするのはいろいろとおかしい(単数が複数になっていたり、頭文字が大文字になっていたり)ので、roomにすべきかと思われます。

投稿2019/02/15 07:20

takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakamasaIijima

2019/02/15 07:26

なるほど. enumにはNSCodingプロトコルは準拠できなかったのですね! 確かにrawValueにして[Int:Int]にすればよかったのですね... ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問