[Swift]ローカルファイルを使用せずにCoreDataをオンメモリ化する方法


どーも。寺坂です

最近、CoreDataのテストを書いている時に、

ローカルのファイルを汚したくないなー
と思ったので、 **メモリ上でデータ管理を行う方法** を紹介します。

## 前提:CoreDataとは

CoreDataは、データを永続化するためのフレームワークの一つです。

多くの場合、SQLiteを利用して使用され、
端末内に.sqliteファイルを作成して、そこにデータを保存します。

このままだと、ファイルが汚れてゴミが残ったり、
読み書きが発生して遅くなりったりするので、

今回は、このCoreDataの保存先を
メモリ上に変更する方法を紹介したいと思います。


※ 使用するコードは、Xcodeでデフォルト生成されるものを元にします。


## 実装1.NSManagedObjectModel

NSManagedObjectModelは、CoreDataのEntityを定義したものです。

これは .momdで保存されるファイルに書かれているので、
まずはそのファイルパスを取得します。


```swift

class CoreDataInMemory {

  let myModuleName = "モジュール名を記述"

  lazy var managedObjectModel: NSManagedObjectModel = {
     let modelURL = NSBundle(forClass: CoreDataInMemory.self).URLForResource(myModuleName, withExtension: "momd")!
     return NSManagedObjectModel(contentsOfURL: self.modelURL)!
     }()

}

```

## 実装2.NSPersistentStoreCoordinator

managedObjectModelを呼んで、
NSPersistentStoreCoordinatorを生成します。

ここで**NSInMemoryStoreType** を指定することによって、
メモリ上で動作するようになります。

参考：<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSPersistentStoreCoordinator_Class/index.html#//apple_ref/doc/constant_group/Store_Types" title="CocoaReference" target="_blank">CoreData Framework Reference   NSPersistentStoreCoordinator Class Reference - Store Types</a>

```swift

class CoreDataInMemory {...

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
        var coordinator:NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        if coordinator?.addPersistentStoreWithType( NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) == nil {
            coordinator = nil
        }
        return coordinator
        }()

...
}

```


## 実装3.NSManagedObjectContext

NSManagedObjectContextの生成。

ここで先ほどのcoordinatorを使用します。

**let coordinator = self.persistentStoreCoordinator**
**managedObjectContext.persistentStoreCoordinator = coordinator**
を忘れると動かないので、ご注意を。


```swift

class CoreDataInMemory {...

    lazy var managedObjectContext: NSManagedObjectContext? = {
        let coordinator = self.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
        }()

...
}

```



## 実装4.saveContext()

データ保存はそのままです。

```swift

class CoreDataInMemory {...

    func saveContext() {
        var error:NSError? = nil
        managedObjectContext?.save(&error)
        if let e = error {
            log.error( CoreDataError(cause: e).description )
        }
    }

...
}

```


## 実装5.解放

nilを入れましょう。

```swift

class CoreDataInMemory {...

    func releaseMemory(){
        persistentStoreCoordinator = nil
        managedObjectContext = nil
    }

...
}

```

## まとめ

以下のようなクラスができました。

テストの時はこちらを使うようにすると、
ストレスレステストができますね。


```swift

class CoreDataInMemory {
    
    let myModuleName = "モジュール名を記述"
    
    lazy var managedObjecar: NSManagedObjectModel = {
        let modelURL = NSBundle(forClass: CoreDataInMemory.self).URLForResource(myModuleName, withExtension: "momd")!
        return NSManagedObjectModel(contentsOfURL: self.modelURL)!
        }()
    
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
        var coordinator:NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        if coordinator?.addPersistentStoreWithType( NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) == nil {
            coordinator = nil
        }
        return coordinator
        }()
    
    
    lazy var managedObjectContext: NSManagedObjectContext? = {
        let coordinator = self.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
        }()
    
    
    func saveContext() {
        var error:NSError? = nil
        managedObjectContext?.save(&error)
        if let e = error {
            log.error( CoreDataError(cause: e).description )
        }
    }
    
    func releaseMemory(){
        persistentStoreCoordinator = nil
        managedObjectContext = nil
    }
    
}

```