SobjectiveRecordとは
SobjectiveRecordはSwift製のCoreData用ライブラリーです。
オープンソースでGithubから自由に利用できます。
Xcode 6.1.1で実装
SobjectiveRecordの特徴
短いコード量でCoreDataを自由に操作できます。
ジェネリックを利用して実装しているのでフェッチ結果を型変換なしで利用できます。
特にバッググラウンド処理をベースにしているのでUIスレッドをブロックせず使うことも可能です。
CoreDataのバッググラウンド処理の詳細は以下の内容を参考してください。
SobjectiveRecordを利用
利用準備
- Github -> SobjectiveRecordからダウンロードして
SobjectiveRecord
フォルダを利用するプロジェクトにコピー、
又はCocoaPodsを利用pod 'SobjectiveRecord'
CocoaPods利用時はCocoaPodsのバージョンを0.36以上にする必要があります。
初期化
import SobjectiveRecord // CocoaPods利用時のみ
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// まずCoreDataの利用前にストアを初期化
NSPersistentStoreCoordinator.setupDefaultStore()
// youre code here
return true
}
Basic
- typealiasを利用してモデルクラスのtypealiasを定義
SobjectiveRecordはフェッチ結果を型変換なしで利用するためのクラスです。
一度定義しておくと後々楽です。
// User, TweetはNSManagedObjectのサブクラス
typealias Users = SobjectiveRecord<User>
typealias Tweets = SobjectiveRecord<Tweet>
// 以降これは同じ
var user = SobjectiveRecord<User>.create()
var user = Users.create()
- 基本、全ての処理は
performBlock:
内で行う。
NSManagedObjectContext.defaultContext.performBlock {
// your code here
}
var moc = NSManagedObjectContext.defaultContext.createChildContext()
moc.performBlock {
// your code here
}
Create / Save / Delete
createメッソドで簡単に作成
サーバーからのJSONデータはDictionaryに変換してそのまま設定可能
NSManagedObjectContext.defaultContext.performBlock {
var t = Tweets.create()
t.text = "I am here"
t.save()
t = Tweets.create(attributes: ["text" : "hello!!", "lang" : "en"])
t.delete()
}
NSManagedObjectContext.defaultContext.performBlock {
Tweets.deleteAll()
NSManagedObjectContext.defaultContext.save()
}
Finders
フェッチ条件は文字列、Dictionary、NSPredicateを設定可能
NSManagedObjectContext.defaultContext.performBlock {
var tweets = Tweets.all()
var tweetsInEnglish = Tweets.find(condition: "lang == 'en'")
var hmhv = Users.first(condition: "screenName == 'hmhv'")
var englishMen = Users.find(condition: ["lang" : "en", "timeZone" : "London"])
var predicate = NSPredicate(format: "friendsCount > 100")
var manyFriendsUsers = Users.find(condition: predicate)
}
Order and Limit
NSManagedObjectContext.defaultContext.performBlock {
var sortedUsers = Users.all(order: "name")
var allUsers = Users.all(order: "screenName ASC, name DESC")
// or
var allUsers2 = Users.all(order: "screenName A, name D")
// or
var allUsers3 = Users.all(order: "screenName, name d")
var manyFriendsUsers = Users.find(condition: "friendsCount > 100", order: "screenName DESC")
var fiveEnglishUsers = Users.find(condition: "lang == 'en'", order: "screenName ASC", fetchLimit: 5)
}
Aggregation
NSManagedObjectContext.defaultContext.performBlock {
var allUserCount = Users.count()
var englishUserCount = Users.count(condition: "lang == 'en'")
}
BatchUpdate
iOS8からの機能であるBatchUpdateも利用可能
NSManagedObjectContext.defaultContext.performBlock {
Users.batchUpdate(condition: "friendsCount > 10", propertiesToUpdate: ["friendsCount": 0])
// update all entities
Users.batchUpdate(propertiesToUpdate: ["friendsCount": 100])
}
NSFetchedResultsController
NSManagedObjectContext.defaultContext.performBlock {
var frc = Users.createFetchedResultsController(order: "name")
frc.delegate = self
var error: NSError? = nil
if frc.performFetch(&error) {
self.reloadData()
}
}
Custom ManagedObjectContext
var childContext = NSManagedObjectContext.defaultContext.createChildContext()
childContext.performBlock {
var john = Users.create(context: childContext)
john.name = "John"
john.save()
var savedJohn = Users.first(condition: "name == 'John'", context: childContext)
var manyFriendsUsers = Users.find(condition: "friendsCount > 100", order: "screenName DESC", context: childContext)
var allUsers = Users.all(context: childContext)
}
カスタムモデル、カスタムsqliteファイルの利用
var modelURL = NSURL.defaultModelURL(modelName: "model_name")
NSPersistentStoreCoordinator.setupDefaultStore(modelURL: modelURL)
// or
var storeURL = NSURL.defaultStoreURL(fileName: "file_name.sqlite")
NSPersistentStoreCoordinator.setupDefaultStore(storeURL: storeURL)
マッピング
ウェブサービスからのJSONはfirst_name
, last_name
のようなスネークケースの場合が多いですが、
Objective-CではfirstName
, lastName
のようにキャメルケースが主流です。
なのでスネークケースからキャメルケースへのマッピングは自動で行われます。
それ以外の特別な名前マッピングが必要な場合は各モデルスラスでmappingsをオーバライドして設定可能です。
!! Date, Transformableタイプ及びRelationshipsはマッピング対象外です。 !!
// just override +mappings in your NSManagedObject subclass
extension User
{
override class var mappings: [String: String]? {
return ["description" : "userDescription"]
}
}
// first_name => firstNameは自動でマッピングされる。
テスト
SobjectiveRecordはメモリ内ストアを設定可能です。テストなどで利用すると便利です。
NSPersistentStoreCoordinator.setupDefaultStore(useInMemoryStore: true)