1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Realm iOSで関係ない値がRLMPropertyとみなされるのをねじ伏せた

Last updated at Posted at 2016-05-24

怪現象

Realm iOSを使っているプロジェクトなのですが、怪現象が起きたのをねじ伏せたのでご報告です。

業務系のアプリで、Http越しにJSONを取得してくるAPIが用意されていて、その結果をDictionaryにまず変換する処理があります。

// 通信結果がdataに入っている
let result = try! NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
let resultDic = result as! Dictionary

なんのことはない、ふつうです。try!でもみ消しているのはひとまず見なかったことにしてください。

続きまして、その結果がネストした構造になっているので、

let value = resultDic["key1"]!["key2"]["key3"]

のように値を取得することを目論みました。nilに厳しいSwiftでして、密かにアンラップなどしております。ちなみにvalueはJSON文字列なので、String型の想定でその後の処理を書いていました。

そしていざビルドしてみると、謎のエラーが出ました……

スクリーンショット 2016-05-24 18.45.26.png

確かにプロジェクト内でRealmを使ってはいるのですが、この時点で処理しているのはパースしただけのJSONオブジェクトであり、RLMObjectとは何の関係もありません。また、実際にdynamicTypeで中身の型を確かめてみると、きっちりと文字列になっております。むりやりにas? String?などしてビルドを通しても、結局該当箇所でクラッシュしてしまいます。

解決策

不可解ですが、ひとまず2つの方法で回避できることがわかりました。
1つ目は、以下のように、毎回キャストすることです。

let key1Dic = resultDic["key1"]! as! Dictionary?
let key2Dic = key1Dic["key2"]! as! Dictionary?
let value = key2Dic["key3"] as! String?

……見るも無残です。
あまりにも醜いその姿を、どうにかして助けてはやれぬものか……

その時私がハッと思い出したのは、イニシエノマホウ、Objective-Cで培ったKey-Value Codingでした。いつもNSDictionaryをパースするのにはあの呪文を唱えていたではないですか……

let loginToken = dic.valueForKeyPath("key1.key2.key3") as! String?

Bravo!!

かくして私は無事にJSONオブジェクト内の文字列を取り出すことに成功したわけであります。

ただし、1点注意があります。上記にも書いていますように、valueForKeyPathはあくまでNSDictionaryのメソッドであって、Dictionaryのそれではございません。イニシエノマホウですからね。以下のように、最初にJSONをパースする際には、NSDictionaryにキャストしてくださいね。

let result = try! NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
let resultDic = result as! NSDictionary // NSDictionaryにする

回想録

というかRealm、ときどきこういう挙動があって驚かされます。基本的には好きなんですけど。同じ現象で困っている人のお役に立てれば。もちろん、根本的な原因など、お心当たりの方はご教授いただけると幸いです。読んでいただきありがとうございました。

1
1
2

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?