hmhv

SobjectiveRecord의 소개

2015-03-09

SobjectiveRecordとは

SobjectiveRecord는 Swift로 작성된 CoreData용 라이브러리.
오픈소스로 Github에서 자유롭게 이용 가능 합니다.

Xcode 6.1.1 로 구현

SobjectiveRecord의 특징

적은 코드량으로 CoreData를 자유롭게 조작 가능하고
제네릭을 이용해 구현을 하여 fecth결과를 형변환없이 사용가능 합니다.
특히 백그라운드 처리를 기본으로 하고 있어 UI쓰레드를 블럭하지 않고 사용할 수도 있습니다.

CoreData의 백그라운드 처리에 대한 상세내용은 아래 글들을 참고하세요.

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는 fecth결과를 형변환없이 사용하기 위한 클래스.
한번만 정의해 두면 두고두고 편합니다.

// 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

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

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

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 은 자동으로 맵핑됨

테스트

HobjectiveRecord은 메모리내 스토어를 설정가능합니다. 테스트 이용에 편리합니다.

NSPersistentStoreCoordinator.setupDefaultStore(useInMemoryStore: true)