どーも。寺坂です
最近、CoreDataのテストを書いている時に、
ローカルのファイルを汚したくないなー
と思ったので、 メモリ上でデータ管理を行う方法 を紹介します。
前提:CoreDataとは
CoreDataは、データを永続化するためのフレームワークの一つです。
多くの場合、SQLiteを利用して使用され、
端末内に.sqliteファイルを作成して、そこにデータを保存します。
このままだと、ファイルが汚れてゴミが残ったり、
読み書きが発生して遅くなりったりするので、
今回は、このCoreDataの保存先を
メモリ上に変更する方法を紹介したいと思います。
※ 使用するコードは、Xcodeでデフォルト生成されるものを元にします。
実装1.NSManagedObjectModel
NSManagedObjectModelは、CoreDataのEntityを定義したものです。
これは .momdで保存されるファイルに書かれているので、
まずはそのファイルパスを取得します。
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 を指定することによって、
メモリ上で動作するようになります。
参考:CoreData Framework Reference NSPersistentStoreCoordinator Class Reference - Store Types
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
を忘れると動かないので、ご注意を。
class CoreDataInMemory {...
lazy var managedObjectContext: NSManagedObjectContext? = {
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
...
}
実装4.saveContext()
データ保存はそのままです。
class CoreDataInMemory {...
func saveContext() {
var error:NSError? = nil
managedObjectContext?.save(&error)
if let e = error {
log.error( CoreDataError(cause: e).description )
}
}
...
}
実装5.解放
nilを入れましょう。
class CoreDataInMemory {...
func releaseMemory(){
persistentStoreCoordinator = nil
managedObjectContext = nil
}
...
}
まとめ
以下のようなクラスができました。
テストの時はこちらを使うようにすると、
ストレスレステストができますね。
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
}
}