본문 바로가기
DataBase/IOS - Realm

IOS) Realm - CRUD Operation & Notification - 3

by 후르륵짭짭 2021. 12. 12.
728x90
반응형

 

안녕하세요!

후르륵짭짭입니다.

저번에 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에서 해주는 것이 좋습니다
728x90
반응형

댓글