Realmを使ってデータ管理【Swift編】-その2-


[Realmを使ってデータ管理【Swift編】-その1-](http://qiita.com/jtemplej/items/1c1b7204341ac01e561e)

前回はRealmを使用してデータの追加/更新/削除等の基本的な項目について書きました。
今回は前回かけなかったRelation、Inmemory、Backgourndに関して書いて行きます。

環境は前回と一緒です。
Bookクラスは前回の定義を引き継いでますので、
まだみていない方は前回から見ていただけると理解が深まると思います。

## Relation
実は出来たりするんですよ奥さん！
やり方は至って簡単なので早速やりましょう。
BookとPublisherの関係で説明していきます。

```swift:Book.swift
import Foundation

import Realm

class Book : RLMObject {
	dynamic var isbn = ""
	dynamic var name = ""
	dynamic var price = 0

	// Publisherを追加.
	dynamic var publisher = Publisher()

    class func find(isbn:String) -> Book? {
        let result = Book.objectsWithPredicate(NSPredicate(format: "isbn = %@", isbn))
        if let books = result {
            return books.firstObject() as? Book
        }
        return nil
    }
    
    override class func primaryKey() -> String {
        return "isbn"
    }
}
```

```swift:Book.swift
import Foundation

import Realm

class Publisher : RLMObject {
	dynamic var id = 0
	dynamic var name = ""
	// Bookを保持
	dynamic var books = RLMArray(objectClassName: Book.className())
    
	override class func primaryKey() -> String {
		return "id"
	}
}
```

単一のオブジェクトを保持する場合は対象のクラスの変数を宣言すればいいのですが
複数のオブジェクトを保持する場合はRLMArrayで定義します.
では実際に定義したオブジェクトを作成してみましょう。

```swift:
let realm = RLMRealm.defaultRealm()
        
// Bookオブジェクト生成.
let book = Book()
book.isbn = "999996"
book.name = "swift tutorial 2"
book.price = 1500
        
// Publisherオブジェクトを生成しBookとの紐付けを行う.
let publisher = Publisher()
publisher.id = 1
publisher.name = "Gihyo"

// bookとpublisherの紐付け.
book.publisher = publisher

// publisherとbookの紐付け.
publisher.books.addObject(book)
        
// Book保存と同時にPublisherも保存される.
realm.beginWriteTransaction()
realm.addOrUpdateObject(book)
realm.commitWriteTransaction()
        
// リレーションが保たれてる.
for result in Book.allObjects() {
	println("book name:\((result as Book).name)")                  // book name:swift tutorial 2
	println("publisher name:\((result as Book).publisher.name)")   // author name:Gihyo
}
for result in Publisher.allObjects() {
	println("publisher id:\((result as Publisher).id)")            // author id:1
	println("book count:\((result as Publisher).books.count)")     // book count:1
}
        
// 先ほど登録したBookを更新.
let results = Publisher.objectsWhere("id = 1")
for result in results {
	let updateBook : Book = (result as Publisher).books[0] as Book
	realm.beginWriteTransaction()
	updateBook.name = "swift tutorial 3"
	updateBook.price = 2000
	realm.addOrUpdateObject(updateBook)
	realm.commitWriteTransaction()
}
        
// 更新されてる.
for result in Book.allObjects() {
	println("book name:\((result as Book).name)")   // book name:swift tutorial
	println("book price:\((result as Book).price)") // book price:2000
}
```

簡単ですが例えばbookのpublisherを設定し忘れて保存してしまうと
bookのpublisherには値がデフォルトのままのpublisherが保存されてしまいます。
publisherのbooksには正しいbookが保存されるのでリレーションが保てないという状態になります。
まぁ気をつけようってことですね！

## Inmemory
あまり使わないと思いますが、メモリ上に保存することも出来ます。
ただし既にRLMRealm.defaultRealm()を呼び出してInstanceを作ったあとだとExceptionを投げてきます。
メモリ上に保存する場合はRLMRealm.useInMemoryDefaultRealm()を呼び出します。

```swift:
RLMRealm.useInMemoryDefaultRealm()
let realm = RLMRealm.defaultRealm()
        
let book = Book()
book.isbn = "999993"
book.name = "realm inmemory tutorial"
book.price = 200
        
realm.beginWriteTransaction()
realm.addOrUpdateObject(book)
realm.commitWriteTransaction()

// 1
println(Book.allObjects().count)

```

処理しているスコープを抜けるまで有効です。
どなたか有効な活用方法を教えてください。。。

## Background
バックグラウンドで保存も出来ます。超簡単！
保存処理自体は通常の処理と変わりません。

```swift:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
	let realm = RLMRealm.defaultRealm()
	realm.beginWriteTransaction()
	let book1 = Book()
	book1.isbn = "999995"
	book1.name = "swift 1.0 tutorial"
	book1.price = 2500
            
	let book2 = Book()
	book2.isbn = "999994"
	book2.name = "swift 1.1 tutorial"
	book2.price = 3500
            
	realm.addOrUpdateObjectsFromArray([book1, book2])
    
	realm.commitWriteTransaction()
            
	for result in Book.allObjects() {
		println("book name:\((result as Book).name)")   // book name:swift tutorial
		println("book price:\((result as Book).price)") // book price:2000
	}
}
```

まだ説明が残っているのがMigrationとNotificationなのですが
長くなりそうなので[Realmを使ってデータ管理【Swift編】-その3-](http://qiita.com/jtemplej/items/10ed4bc0cc6519682e6e)に続けます。
次こそ最後！