저장할 때 structure를 직접 저장하고 가져올 때도 structure를 직접 가져온다. 처음엔 이게 무슨 장점인가 싶었는데, rdb에서 직접 쿼리를 날려서 그 값들을 구조체에 다시 채울 필요를 줄여주니 좋다.(그리고 속도도 빠르다고 하는데...음...그건 모르겠음.)
그래도 swift에서 사용하는 sqlite나 mysql도 랩핑해서 만들면 realm처럼 비슷하게 만들 수 있을 것이다.
그리고 아래에서 설명 하겠지만 가져온(select) 구조체 변수(realm data)가 다른 위치에서 값이 변경될 경우 자동으로 내가 가져온 구조체 변수에 반영된다.
아무튼 사용해보니 편하긴 하다.
전체 문법 및 자세한 사용법은 https://realm.io/kr/docs/swift/latest/#getting-started 확인가능.
cocoapod을 이용해서 xcode project에 realm을 추가한 후 사용하면 된다.(pod 'RealmSwift')
우선 저장할 클래스(구조체)를 만든다.
class PopupPageList_Object: Object {
@objc dynamic var version: Int = 0;
var force_list = List<String>();
var page_list = List<String>();
}
realm 라이브러리에 있는 Object를 상속받아서 class를 만들어야 한다.
일반적인 자료형 Int 멤버에 dynamic이 붙어 있는데 dynamic을 붙여야 하는 이유에 대해서 다음과 같이 설명하고 있다.
"dynamic키워드는 모델 변수에 대한 변경 사항을 Realm에 알리고, 결과적으로 이를 데이터베이스에 반영할 수 있도록 허용합니다."
그리고 List는 배열인데 dynamic 문법이 필요 없다.
realm을 조금이라도 편하게 사용하기 위해 다음의 랩핑 클래스를 만들었다.
내부 소스 보면 별거 없다. 그냥 함수 하나로 합쳐놓았을 뿐. 아래에 기록되는 예제 소스부터는 위 랩핑 클래스를 사용한다.
참고로 realm은 동기로 동작한다.
realm에 insert는 다음과 같이 한다.
let newVal = PopupPageList_Object()
let _ = realmInsert(object: newVal)
realm에 select는 다음과 같이 한다.
let result = realmSelect(PopupPageList_Object.self);
위와 같이 하면 result에 PopupPageList_Object 객체 전부가 다 들어간다. 즉 배열. 만약 하나만 있을 경우 result.first 하면 된다. mysql처럼 select 할 때 where 절이 필요하다면 다음과 같이 하면 된다.
realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version = %@", version)).first
그냥 여러개(배열)를 받을 경우 다음과 같이 first만 빼면 된다.
realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version > %@", version))
만약 위와 같이 여러 값이 선택되었는데, swift의 array type으로 변경하고 싶을 경우 다음과 같이 하면 된다.
let results = realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version > %@", version))
let arrayResult = Array(results) //위 랩핑 클래스를 사용해야 가능하다. extension Results 부분 확인
realm에 update는 다음과 같이 한다.
let _ = realmUpdate {
object.version = 1; //object는 realmSelect를 통해 가져온 PopupPageList_Object의 instance
}
realmSelect를 통해 가져온 class instance를 위와 같이 블럭으로 감싸지 않고
object.version = 1
이렇게만 사용할 경우 crash가 발생할 수 있다.
realm에 delete는 다음과 같이 한다. 우선 지우려면 realm에서 select한 값을 지우거나 클래스에 값을 채운 다음 delete 명령을 호출하면 된다. 기본적으로 delete는 여러개를 동시에 지울 수 있다고 생각하면 된다.
let result = realmSelect(PopupPageList_Object.self);
let _ = realmDelete(result);
위 코드는 PopupPageList_Object 전부를 선택한 후 모두 지우는 코드이다.
위 코드는 PopupPageList_Object 전부를 선택한 후 모두 지우는 코드이다.
let result = realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version > %@", version))
let _ = realmDelete(result);
위 코드는 version이 특정 값 이상인 것을 전부 지우는 것이다.
마지막으로 select 할 때 정렬은 다음과 같이 하면 된다.
let results = realmSelect(PopupPageList_Object.self).sorted(byKeyPath: "version", ascending: false)
그리고 realm의 특징인 변경된 값이 바로 반영되는 것을 확인해보면...
let result = realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version = %@", version)).first
위와 같이 select를 해서 하나의 값을 가져왔다. 그런데 다른 위치에서 realm update가 일어나면 위 result 변수에 바로 반영된다.
예를 들어 PopupPageList_Object의 version 값이 모두 2로 변경된다면 위 result의 version 값도 2로 변경되어 있다.
만약 mysql이였다면 다시 select를 해야하는데 그럴 필요가 없는 것이다.
위 특징을 이용해 realm 무조건 하나만 저장되는 class가 있고, 그 값이 다른 곳에서 변경될 수 있다면 다음과 같이 class를 만들어 사용하면 될 것 같다.
처음 앱이 시작될 때 RealmPopupPageList.initialize() 를 한번만 호출해주고, 그 뒤로는 RealmPopupPageList.value 값을 이용해서 사용하면 된다. 그러면 어느곳에서 수정을 해도 변경된 값을 바로 사용할 수 있다.
그리고 realm의 특징인 변경된 값이 바로 반영되는 것을 확인해보면...
let result = realmSelect(PopupPageList_Object.self, predicate: NSPredicate(format: "version = %@", version)).first
위와 같이 select를 해서 하나의 값을 가져왔다. 그런데 다른 위치에서 realm update가 일어나면 위 result 변수에 바로 반영된다.
예를 들어 PopupPageList_Object의 version 값이 모두 2로 변경된다면 위 result의 version 값도 2로 변경되어 있다.
만약 mysql이였다면 다시 select를 해야하는데 그럴 필요가 없는 것이다.
위 특징을 이용해 realm 무조건 하나만 저장되는 class가 있고, 그 값이 다른 곳에서 변경될 수 있다면 다음과 같이 class를 만들어 사용하면 될 것 같다.
protocol RealmProtocol {
static func initialize();
static func clear();
}
class RealmPopupPageList: RealmProtocol {
static var value: PopupPageList_Object? = nil;
static var config: PopupPageList_Object? {
get {
let result = realmSelect(PopupPageList_Object.self);
return result.first;
}
set(newVal) {
if newVal == nil {
return;
}
let temp = config;
if temp == nil {
let _ = realmInsert(object: newVal!);
}
else {
let _ = realmUpdate {
temp!.version = newVal!.version;
temp!.force_list.removeAll();
temp!.force_list.append(objectsIn: newVal!.force_list);
temp!.page_list.removeAll();
temp!.page_list.append(objectsIn: newVal!.page_list);
}
}
}
}
static func initialize() {
if config == nil {
config = PopupPageList_Object();
}
value = config;
}
static func clear() {
//필요없음.
}
}
처음 앱이 시작될 때 RealmPopupPageList.initialize() 를 한번만 호출해주고, 그 뒤로는 RealmPopupPageList.value 값을 이용해서 사용하면 된다. 그러면 어느곳에서 수정을 해도 변경된 값을 바로 사용할 수 있다.
댓글 없음:
댓글 쓰기