CoreDataを触ってみる

今まで作ったアプリは、ハイスコアの保存などを行うためにNSUserDefaultsを使っていましたが、今回Todoアプリの試作を行うにあたり、CoreDataというものに触れてみます。触りだけなので、とてもシンプルです。備忘録を兼ねてまとめておきます。

## 動作イメージ
![coredata.gif](https://qiita-image-store.s3.amazonaws.com/0/70446/d720b10b-11a9-3f8f-2b42-2ac6a84547ff.gif)

## CoreDataとは
オブジェクトを永続化するためのフレームワークで、オブジェクトとリレーショナルデータベースであるSQLiteとの間を取り持ってくれるもの。どこかで耳にしたことのある「O/Rマッピング」とは、まさにCoreDataのことでした。

## CoreDataを使用する準備

- NSManagedObjectModelオブジェクトの作成
- NSPersistentStoreCoordinatorオブジェクトの作成
- NSManagedObjectContextオブジェクトの作成

プロジェクト作成時に、「Use Core Data」にチェックを入れると上記準備をしてくれます。AppDelegateに該当のソースが自動的に追記されます。

## エンティティの作成
CoreDataのモデルエディタから"ToDo"エンティティを作成し、Attributesに"memo"をString型で追加します。
![coredata.png](https://qiita-image-store.s3.amazonaws.com/0/70446/8761d20f-4805-76fb-7e2b-034a2aac4f90.png)

## 画面の作成
![coredata2.png](https://qiita-image-store.s3.amazonaws.com/0/70446/6ef96a56-47f7-5c39-df2e-bbfa6eec9298.png)

## ViewControllerの修正
```swift:ViewController.swift
import UIKit
import CoreData

class ViewController: UIViewController {
    
    var obj : NSManagedObject? = nil

    @IBOutlet weak var tfMemoCreate: UITextField!
    @IBOutlet weak var tfMemoRead: UITextField!
    @IBOutlet weak var tfMemoUpdate: UITextField!
    
    // Save
    @IBAction func btnSaveAction() {
        if(tfMemoCreate.text == "") {
            return
        }
        // Get ManagedObjectContext
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext!
        
        // Create new ManagedObject
        var newTodo = NSEntityDescription.insertNewObjectForEntityForName("ToDo", inManagedObjectContext: managedContext) as NSManagedObject
        newTodo.setValue(tfMemoCreate.text, forKey: "memo")
        
        // Error handling
        var error: NSError?
        if !managedContext.save(&error) {
            println("Could not save \(error)")
        }
        println(newTodo)
        println("Object Saved")
    }
    
    // Read
    @IBAction func btnLoadAction() {
        if(tfMemoRead.text == "") {
            return
        }
        // Get ManagedObjectContext
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext!
        
        // Set search conditions
        let fetchRequest = NSFetchRequest(entityName: "ToDo")
        fetchRequest.returnsObjectsAsFaults = false
        fetchRequest.predicate = NSPredicate(format: "memo = %@", tfMemoRead.text)
        var error: NSError?
        
        // Get result array from ManagedObjectContext
        var fetchResults: Array = managedContext.executeFetchRequest(fetchRequest, error: &error)!
        if(fetchResults.count > 0){
            obj = fetchResults[0] as? NSManagedObject
            let memo: String = obj!.valueForKey("memo") as String
            tfMemoUpdate.text = memo
            println(obj)
            println("Object Read")
        }else {
            println("Could not fetch \(error)")
            tfMemoUpdate.text = "Error: Memo Nothing."
        }
    }
    
    // Update
    @IBAction func btnUpdateAction() {
        // Get ManagedObjectContext
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext!

        // Change value of managedObject
        if(obj != nil){
            obj?.setValue(tfMemoUpdate.text, forKey: "memo")

            // Save value to managedObjectContext
            var error: NSError?
            if !managedContext.save(&error) {
                println("Could not update \(error)")
            }
            tfMemoUpdate.text = obj?.valueForKey("memo") as String
            println(obj)
            println("Object updated")
        }
        
    }
    
    // Delete
    @IBAction func btnDeleteAction() {
        // Get ManagedObjectContext
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext!
        
        // Delete managedObject from managed context
        if(obj != nil){
            println(obj)
            managedContext.deleteObject(obj!)
            
            // Save value to managed context
            var error: NSError?
            if !managedContext.save(&error) {
                println("Could not update \(error)")
            }
            obj = nil
            println("Object Deleted")
            tfMemoUpdate.text = ""
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
```

## 参考
[SwiftでCoreData実装](http://qiita.com/ryusukefuda/items/4f25a0fbe4cf99104266)
[Swiftお勉強 – CoreDataでCRUD操作サンプル](http://blog.landfront.info/archives/286)