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에 따라 데이터가 하나하나 종속되기 때문에
모든 종속 데이터를 한번에 가져와야 하는 경우 손이 많이 간다.
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로 데이터를
정제해서 썼다.