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

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

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

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

2回答

6055閲覧

RealmSwiftに対応したModelがうまくインスタンス化できない

YoheiFusayasu

総合スコア20

Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

3グッド

3クリップ

投稿2015/12/11 10:30

編集2015/12/17 07:41

RealmSwiftに対応したModelをObjectMapperを使って実装しています。

以下の状態で、Realmの「Object」を継承しなければObjectMapperによってインスタンスを生成できます。

Swift

1import Foundation 2import ObjectMapper 3import RealmSwift 4 5class Question: Mappable { 6 7 dynamic var id: Int = 0 8 dynamic var title: String = "" 9 dynamic var body: String = "" 10 dynamic var created: Double = 0 11 dynamic var modified: Double = 0 12 dynamic var count_reply: Int = 0 13 dynamic var count_pv: Int = 0 14 15 class func newInstance(map: Map) -> Mappable? { 16 return Question() 17 } 18 19 required convenience init?(_ map: Map){ 20 self.init() 21 } 22 23 func mapping(map: Map) { 24 id <- map["id"] 25 title <- map["title"] 26 body <- map["body"] 27 created <- map["created"] 28 modified <- map["modified"] 29 count_reply <- map["count_reply"] 30 count_pv <- map["count_pv"] 31 } 32} 33

しかし

Swift

1class Question: Object, Mappable { 2 中略 3}

とした時に必ずRLMExceptionになってしまい、落ちてしまいます。

エラー内容は以下です。

txt

1Terminating app due to uncaught exception 'RLMException', reason: ''NSArray' is not supported as an RLMObject property. All properties must be primitives, NSString, NSDate, NSData, RLMArray, or subclasses of RLMObject. See http://realm.io/docs/objc/api/Classes/RLMObject.html for more information.'

NSArrayではダメだとかいてあるのですが、RealmSwift公式ドキュメントでは以下のようにDictionaryで渡しています。

swift

1// (2) Dictionaryの値を使ってDogクラスのオブジェクトを作成する 2let myOtherDog = Dog(value: ["name" : "Pluto", "age": 3])

また私のコード上では以下のようにしてインスタンスを生成しています。

swift

1let questions = json["questions"].arrayObject 2 3for subJson in questions! { 4 let question: Question = Mapper<Question>().map(subJson)! 5 self.questions.append(question) 6}

Clip Model

Swift

1class Clip: Object, Mappable { 2 3 // MARK: Realm - stored properties 4 5 dynamic var id: Int = 0 6 dynamic var title: String = "" 7 dynamic var created: Double = 0 8 dynamic var modified: Double = 0 9 dynamic var count_reply: Int = 0 10 dynamic var count_pv: Int = 0 11 dynamic var is_beginner: Bool = false 12 dynamic var is_accepted: Bool = false 13 dynamic var is_presentation: Bool = false 14 dynamic var tags: [String] = [] 15 var user: User = User() 16 var replies = List<Reply>() 17 18 // MARK: ObjectMapper 19 20 class func newInstance(map: Map) -> Mappable? { 21 return Clip() 22 } 23 24 required convenience init?(_ map: Map){ 25 self.init() 26 } 27 28 /// Mapping between ObjectMapper (JSON) and the model properties 29 func mapping(map: Map) { 30 id <- map["id"] 31 title <- map["title"] 32 created <- map["created"] 33 modified <- map["modified"] 34 count_reply <- map["count_reply"] 35 count_pv <- map["count_pv"] 36 is_beginner <- map["is_beginner"] 37 is_accepted <- map["is_accepted"] 38 is_presentation <- map["is_presentation"] 39 tags <- map["tags"] 40 user <- map["user"] 41 replies <- map["replies"] 42 } 43}

このRealmモデルは下記のGistを参考に作りました。

Transform arrays with ObjectMapper to Realm's List type

なぜうまくいかないのかお分かりになる方がいればよろしくお願いします。

arly_times, afroscript, ikuwow👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2015/12/14 08:49

私の環境では、上記のモデルに対して、`let question = Mapper<Question>().map(string)`などとして、Questionのインスタンスを作成することができましたが、どのような例外が起こっているのでしょうか?ちなみに、Realmに保存したモデルからJSONに変換するのはObjectMapperでは多少問題があります。
YoheiFusayasu

2015/12/17 04:16

遅くなって申し訳ありません。 訂正依頼ありがとうございます。 追記いたしました。
退会済みユーザー

退会済みユーザー

2015/12/17 07:06

その例外は、Realmが初期化時の最初の一回、モデルの構造を読み込んでいる最中に出るもので、モデルのプロパティにNSArrayは使用できないということを示しています。本当に定義しているモデルは上記で合っていますか?また、他のモデルでNSArrayをプロパティにしているものがありませんか?おそらく、Questionクラスには問題がないのですが、他のクラスにRealmのモデルとして正しくない定義のものがあり、QuestionをObjectのサブクラスにするとRealmの初期化が動作するので、その別のモデルクラスがエラーになってるのではないかと推測しています。
YoheiFusayasu

2015/12/17 07:28

なるほどです。全く理解できていませんでした・・ 他のモデルのプロパティにNSArrayがあります。この場合何で置き換えるのが妥当なのでしょうか。ドキュメントにはListがArrayの代わりになるが、RLMオブジェクトのサブクラスしか格納できないと記載されているのですが、格納したいデータを一旦RLMオブジェクト化するのが最適な方法でしょうか。
退会済みユーザー

退会済みユーザー

2015/12/17 07:31

> 一旦RLMオブジェクト化するのが最適な方法でしょうか たいていはそうなります。最適なデータモデリングというのはケースバイケースなので、差し支えなければ、その他のモデルの定義も載せてもらえませんか?察するにteratailのAPIレスポンスをモデリングしようとしてるのですよね?
YoheiFusayasu

2015/12/17 07:42

おっしゃる通りのことを実装しようとしています。おそらくこちらのタグを[String]で定義している部分でハマっているのだと思います。
退会済みユーザー

退会済みユーザー

2015/12/17 07:50

この場合は、Tagのモデルを定義して、それの関連にするのがいいと思います。`class Tag: Object { dynamic var tagName = "" dynamic var explain = "" dynamic var created = NSDate() }`で、プロパティの方は`let tags: List<Tag>`ですね。APIによってタグの構造全部を返すものと名前だけ返すものがあるようですが、名前だけ返すものについては名前で検索して、保存済みのTagがあればそれを、なければ`explain`と`created`は空で名前だけの`Tag`を作って、後でタグのAPIを叩く機会があった時に更新するようにすると良いと思います。
YoheiFusayasu

2015/12/17 08:06

詳しくありがとうございます!実装し終わりましたらまたここにレスをさせていただきます。
YoheiFusayasu

2015/12/17 11:04

ご指導いただいた通りに変更しましたところきちんとインスタンス化することができました。詳しいご説明ありがとうございました。 ベストアンサーに選びたいのですが、この欄への投稿をコピペして回答欄に入力していただけるとありがたいです。
guest

回答2

0

ベストアンサー

私の環境ではご提示のモデルクラスとコードで問題なく動作しているので、原因は他のモデルにあると考えられます。
QuestionObjectのサブクラスにするかどうかで結果が変わるのは、Objectのサブクラスにアクセスすることで、Realmの初期化処理が働くためです。
(Realmが初期化時に他の問題のあるモデルの定義を読み込むために例外が起こっている)

この例外は、現在Realmで未サポートのNSArrayのプロパティがモデルに定義されていることによって起こります。
Question以外のモデルにそのような定義がなされていると思いますので、調べてRealmのモデルとして正しい形に修正してください。

修正の方法はケースバイケースですが、たいていは、NSArrayで保持しようとしている内容でObjectのサブクラスを定義して、関連としてListで保持するのが良いと思います。

投稿2015/12/17 15:37

編集2015/12/17 15:39
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

YoheiFusayasu

2015/12/17 15:39

ありがとうございました。おかげさまでRealmの理解も深まりました。
guest

0

まずは RLMException のエラー内容を追記したほうがいいかもしれません。

もしエラー内容に migration 等あれば、一旦アプリを削除してから再実行してみてください。

投稿2015/12/11 11:28

sora0077

総合スコア14

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

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

YoheiFusayasu

2015/12/17 04:25

遅くなり申し訳ありません。ありがとうございます。エラー内容を追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問