How To Use RealmEmbeddedObject

import RealmSwift
import Then

 open class KeywordEngine: Object, ObjectKeyIdentifiable {
    
     @Persisted(primaryKey: true) public var keywordType: Int = 0 // 키워드 타입
     @Persisted public var name: String = "" // 검색엔진명
     @Persisted public var priority: Int = 0 //순번
     @Persisted public var keywords: List<Keyword> // 키워드 목록
     @Persisted public var isConnected: Bool = false // 연결 여부
     @Persisted public var isAuthenticated: Bool = false // 인증 여부
     @Persisted public var timestamp: Date = Date() // 등록 및 수정 날짜
    
     
     convenience init(keywordType: Int, name: String, priority: Int, keywords: [Keyword], isConnected: Bool, isAuthenticated: Bool, timestamp: Date) {
         self.init()
         self.keywordType = keywordType
         self.name = name
         self.priority = priority
         self.keywords.append(objectsIn: keywords)
         self.isConnected = isConnected
         self.isAuthenticated = isAuthenticated
     }
    
}

예전에는 @objc dynamic var 로 설정했다면 업데이트 되면서는
@Persisted로도 선언이 가능하다.

open class Keyword: EmbeddedObject {
    
    @Persisted public var id: CLong = 0// 키 ( 인덱스 )
    @Persisted public var keywordType: Int = 0 // 키워드 타입
    @Persisted public var mainType: Int = 0 // 메인 종류 ( 유튜브[1:유튜브, 2:유튜브뮤직] / 구글[null] )
    @Persisted public var subType: Int = 0 // 검색어 종류 ( 0:기타, 1:검색, 2:시청, 3:방문, 4:조회 )
    @Persisted public var name: String = "" // 검색어
    @Persisted public var dateTime: Date = Date() // 주문 날짜
    @Persisted public var image: String = "" // 썸네일 이미지 URL
    @Persisted public var timestamp: Date = Date() // 등록 및 수정 날짜
    
}

객체는 위의 두개의 코드 예시대로 설정하면 된다.

   public func getLastDate(keywordType: Int) -> Date {
        var lastDate : Date = getCustomedZeroDate()
        let keywordLastDate = realm.objects(KeywordEngine.self).filter("ANY keywords.keywordType = %@", keywordType).first?.keywords.sorted(byKeyPath: "dateTime", ascending: false).first?.dateTime ?? getCustomedZeroDate()
        
        lastDate = keywordLastDate
        return lastDate
        }
    }

임베디드 오브젝트의 최대 단점은 쿼리가 길어지고
부모의 PK에 따라 데이터가 하나하나 종속되기 때문에
모든 종속 데이터를 한번에 가져와야 하는 경우 손이 많이 간다.

  • 안드로이드는 위의 선언한 Keyword 객체에 직접 접근해서 읽기는 되나,
    쓰기와 업데이트는 해도 반영이 안 된다고 한다.
   public func insertFormattedKeyword(keywords: [Keyword], promise: @escaping(Result<Bool,Error>) -> Void) {
        
        realm.executeTransactionAsync {
            do {
                guard let keywordEngine = realm.object(ofType: KeywordEngine.self, forPrimaryKey: keywordType) else {
                    print("Contact \(keywordType) not found")
                    return
                }
                try realm.write() {
                    print("KEYWORD COUNT DAO :: \(keywords.count)")
                    keywordEngine.keywords.append(objectsIn: keywords)
                }
                promise(.success(true))
            } catch let error {
                print("\(error)")
                promise(.failure(error))
            }
        }
        
    }

위의 코드는 읽기 코드이다.
하나의 트랜잭션에서 부모뷰를 먼저 불러준 후 임베디드 데이터인
'keywords'에 접근해서 write를 하면 된다.

임베디드를 사용하게 될 경우 반드시 고려해야하는 것이
물리적으로 종속이 되야하는지, 반드시 임베디드가 아니면 안 되는지
고려해봐야할 것 같다. 읽거나 쿼리하는 부분이 복잡해지기 때문이다.

개발을 하면서 임베디드 오브젝트는 접근이 너무 힘들다고 했는데,
접근자체는 어렵지 않았으나 자료와 사례가 너무 없었고,
StackOverFlow에는 많은 사람들이 .compactMap과 .filter로 데이터를
정제해서 썼다.

좋은 웹페이지 즐겨찾기