LoginSignup
6
8

More than 5 years have passed since last update.

Swift|Tuple(タプル)型をDictionary(辞書)型に変換

Last updated at Posted at 2016-03-17

前提

環境
- Xcode 7.2.1
言語
- Swift 2.1

やりたいこと

  • Tuple型をDictionary型に変換
  • NSUserDefaultsを使ってデータを保存
  • データの取り出し

なぜ変換するかというと、
たとえば、
Tuple型はそのままNSUserDefaultsに保存できない。(詳しい理由は下に)

Tuple Type (タプル)

ざっくりに説明すると、異なる型の値を括弧とコンマでまとめる型である.

値に名前を付けずに宣言する

タプルは値に名前を付けて宣言することができるが、
名前を付けなくてもタプル型は、(0番, 1番, 2番)のように値を参照する。

var tuple1 = ("str", 1234, true)

print(tuple1) // -->> ("str", 1234, true)

print(tuple1.0) // -->> str
print(tuple1.1) // -->> 1234

// Arrayもオッケー
var tuple2 = ("myArray1", 1, ["apple", "banana", "cherry"])

print(tuple2.2) // -->> ["apple", "banana", "cherry"]

//おまけ -->> タプルの値の数をカウント
let count = Mirror(reflecting: tuple2).children.count // -->> 3

値に名前を付けて宣言する

var tuple3 = (name: "Andy", score: 1234, cheated: true)

print(tuple3.name) // -->> Andy
print(tuple3.score) // -->> 1234

変換

Dictionaryに変換

typealias convertTuple = (name1: String, name2: Bool, name3: Int)
typealias convertDictionary = [String: Any]

let name1 = "name1"
let name2 = "name2"
let name3 = "name3"

func serializeTuple(xtuple: convertTuple) -> convertDictionary {
    return [
        name1 : xtuple.name1,
        name2 : xtuple.name2,
        name3 : xtuple.name3
    ]
}

Tupleに戻す

func deserializeDictionary(xdictionary: convertDictionary) -> convertTuple {
    return convertTuple(
        xdictionary[name1] as! String!,
        xdictionary[name2] as! Bool!,
        xdictionary[name3] as! Int!
    )
}

使ってみる

var tupleWantToConvert: convertTuple = (name1: "Hello", name2: false, name3: 1234)
let convertedDictionary = serializeTuple(tupleWantToConvert) 
// -->> ["name2": false, "name3": 1234, "name1": "Hello"]
let convertedTuple = deserializeDictionary(convertedDictionary)
// -->>> (.0 "Hello", .1 false, .2 1234) 順番戻る

ちょっとまとめる

  • かなり手間がかかる
  • Tupleの名前が多いときは推奨できない
  • Dictionary型に変換したときのデータの順番は保証できない -->> 公式ドキュメント

辞書型の順番は気にすることないと思うが、
問題はTupleの値の名前が多すぎると、上のコードのように値の名前と型を合わせる手間が多くなるので、初めから辞書型を使うといいかもしれない。

これについて、もっと良い変換方法があれば、是非コメントをお願いします!

Tuple型のNSUserDefaults保存

Tuple型を変換せずにNSUserDefaultsを使って保存するとエラーが生じる。(理由は下)
解決策として、

  • Tuple型をDictionary型に変換
  • NSDataにエンコーディング
  • String型に変換(実用的ではない)

Tuple型は簡単にNSCoding使えないため、ちょっと手間がかかる。

読み書き

var tupleWantToConvert: convertTuple = (name1: "Hello", name2: false, name3: 1234)

// 書き込む
let convertedDictionary = serializeTuple(tupleWantToConvert)
NSUserDefaults.standardUserDefaults().setObject(myConvertedDictionary, forKey: "DATA")

// 読み込む
let fetchedDictionary = NSUserDefaults.standardUserDefaults().dictionaryForKey("DATA") as convertDictionary
// Tuple型で利用したいとき
let fetchedTuple = deserializeDictionary(fetchedDictionary)

なぜ保存できないか

Appleの公式ドキュメントFoundation Framework Referenceから一部抜粋

The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData. For more details, see Preferences and Settings Programming Guide.

太字でマークした箇所を見ると、扱えるデータとして、
NSData, NSString, NSNumber, NSData, NSArray, NSDictionaryがある。
さらに前の文に型として、
(複数の)Double, Float, Int, Boolean, URLを保存することができる。
これによるとNSUserDefaultsはTupleを扱うことができない。

解決方法は太字マークの後ろに、保存したいものをNSDataにすること。

今回はTuple型、クラスではないため、そのままエンコーディングすることはできない。方法としては、タプル内の値を一個一個抽出して、エンコーディングを行う。NSDataとしてNSUserDefaultsに保存する。

GitHub

Download Zipでswiftのplaygroundがダウンロードされる
convertTupleToDictionary

6
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8