안녕하세요!
후르륵짭짭입니다.
저번에 Realm에 대한 글을 작성 했는데,,,,
사라졌네요,,, 너무 ㅂㄷㅂㄷ 합니다.
사내 맥북 키보드가 맛탱이가 가서 그런지
한영변환이 잘 안되네요 ㅠㅠ
점점 블로그 작성이 쉽지 않습니다 ㅠㅠ
** Notification Realm **
Realm에는 데이터값 변경을 알려주는 Notification을 제공합니다.
총 3가지 타입에 대해 제공을 하는데,
1. Realm Notification
2.Collection Notification
3. Object Notification
** Notification Setting **
노티피케이션을 등록 하기 위해서는 반드시!!!
인스턴스 변수로 노티피케이션을 넣어줘야합니다.
class ViewController: UIViewController {
var users : Results<User>?
var notificationToken : NotificationToken?
var notificationToken2 : NotificationToken?
var notificationToken3 : NotificationToken?
.
.
.
}
** Realm Notification **
이것은 가장 HEAD에 해당하는 저장데이터에 대한 노티피케이션 입니다.
- 세팅 -
그래서 우선적으로 User객체를 인스턴스 변수로 만들고
등록을 해줍니다.
func insertObjectIfNotExistsIntoTheRealm(){
let realm = try! Realm()
users = realm.objects(User.self) //Realm 등록
print("Before Insert Live Result\(String(describing: users?.count))")
//Before Insert Live ResultOptional(0)
Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { _ in
if(self.users?.count == 0){
let user = self.createRealmObject(name: "Hello", id: 0)
try! realm.write({
realm.add(user, update: .all)//동일한 기준키가 있다면 변경해준다.
})
print("After Insert Live Result\(String(describing: self.users?.count))")
// After Insert Live ResultOptional(1)
}
}
}
- 노티피케이션 등록 -
그리고 Notification을 등록 해줍니다.
notificationToken = users?.observe({ changes in
if Thread.isMainThread {print("Main Thread")}
switch changes {
case let .initial(users):
print("Initial case \(users.count)")
//Initial case 0
case let .update(users, deletions: deletions, insertions: insertions, modifications: modifications):
print("update case : \(users.count)")
print("deletions : \(deletions)")
print("insertions : \(insertions)")
print("modifications : \(modifications)")
//해당 DELETIONS , INSERTIONS, MODIFICATIONS 는 모두 DB Table의 INDEX를 의미한다.
/*
update case : 1
deletions : 0
insertions : 1
modifications : 0
*/
/*
update case : 1
deletions : 0
insertions : 0
modifications : 1
*/
case .error(let error):
print(error.localizedDescription)
}
})
이렇게 노티피케이션을 등록 해준다면
변경이 될 때 마다. 삭제인지, 추가인지, 수정인지 알려주게 됩니다.
그리고 해당 매개변수에는 User 테이블의 Index 값을 나타냅니다.
** Collection Notification **
Header Realm 내부에 RealmArray에 대한 Notification의 변경 값에 대한 감지 입니다.
즉 일대 다 관계에 대한 노티피케이션 입니다!
- Notification 등록 -
//Collection Level 노티피케이션
notificationToken2 = users?[0].todos.observe { todoChange in
if Thread.isMainThread {print("Main Thread")}
switch todoChange{
case .initial(let todo):
print("Initial todo count : \(todo.count)")
case let .update(todo, deletions: deletions, insertions: insertions, modifications:modifications):
print("update todo totoal : \(todo.count)")
if deletions.count > 0 {
print("delete index : \(deletions)")
/*
update todo totoal : 2
delete index : [0]
*/
}
if insertions.count > 0 {
print("insertion index : \(insertions)")
}
if modifications.count > 0 {
print("modifications index : \(modifications)")
/*
update todo totoal : 2
modifications index : [0]
*/
}
case let .error(error):
print(error.localizedDescription)
}
}
- 추가 -
func insertTodoAfter10Sec(){
Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
let realm = try! Realm()
if let users = realm.objects(User.self).filter("userId == 1").first {
let todo = Todo("GCD", "Need to create GCD blog")
try! realm.write({
users.todos.append(todo)
print(users.todos.count) //4
})
}
}
}
- 변경 -
func updateTodoList(){
Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { _ in
let realm = try! Realm()
if let user = realm.object(ofType: User.self, forPrimaryKey: 1) {
try! realm.write({
user.todos[0].name = "Update RxSwift"
})
}
}
}
- 삭제 -
func deleteTodoList(){
Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { _ in
let realm = try! Realm()
if let user = realm.object(ofType: User.self, forPrimaryKey: 1) {
try! realm.write({
realm.delete(user.todos[0])
})
}
}
}
** Object Notification **.
Header Realm 내부의 일대일 관계를 형성하고 있는 객체에 대한 Notification
이 노티피케이션은 기존의 것과 다른 이유가 일대일 관계이기 때문에
추가에 대한 설정이 없습니다.
- Notification 등록 -
//Object Level 노티피케이션
notificationToken3 = users?[0].passport?.observe({ objectChange in
if Thread.isMainThread {print("Main Thread")}
switch objectChange{
case .error(let err):
print(err.localizedDescription)
case .change(let object , let properties): //값변경
print("object : \(object)")
for p in properties {
print("name : \(p.name)")
print("newValue : \(p.newValue)")
print("oldValue : \(p.oldValue)")
//Thread가 다를 때만 OldValue의 값을 알 수 있다.
}
case .deleted: //값 삭제
print("Object Delete")
}
})
- 변경 -
func updatePassport(){
//Main Thread에서 하면 올드벨류를 알 수 없게 된다.
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
let realm = try! Realm()
if let user = realm.object(ofType: User.self, forPrimaryKey: 1) {
try! realm.write({
user.passport?.passportNumber = "pass 2"
})
}
}
}
** 참고사항 **
Notification은 Thread가 서로 달라야 값을 인지 할 수 있습니다.
따라서 Notification 등록은 Main Threa에서 하고
값 수정 삭제 추가는 Background Threa에서 해주는 것이 좋습니다
'DataBase > IOS - Realm' 카테고리의 다른 글
IOS)Realm - Migration (0) | 2022.05.23 |
---|---|
IOS)Realm - Multi Threading (0) | 2022.04.28 |
IOS)Realm - Configuration & Extension Realm Share - 1 (0) | 2022.02.13 |
IOS) Realm - CRUD Operation & Notification - 2 (0) | 2021.12.04 |
IOS) Realm - CRUD Operation & Notification - 1 (0) | 2021.12.04 |
댓글