When should We Send Sign To Observer?
- Combine Future를 사용하면서 Realm의 Transaction이 정확히 언제 끝나는지
- 그 때는 언제인지 어떻게 보내야 하는지 생각보다 문서가 없었고, 시도되지 않은 것 같아서 글을 남긴다.
Why We Use Combine Future?
- RealmToken을 쓰면 UI업데이트는 다 거기서 하면 되지 않냐고 생각하는 사람이 있겠지만,
- 생각보다 순차적으로 일이 끝나야하고 세부 컨트롤이 들어가야하는 일이 많다.
- RealmToken으로 다 해결되면 내가 이 글을 안 쓰고 있었을 것 같다.
CodeLab
public func insertFormattedKeyword(keywordEngineType: Int, keywords: [Keyword], promise: @escaping(Result<Bool,Error>) -> Void) {
realm.executeTransactionAsync {
do {
guard let keywordEngine = realm.object(ofType: KeywordEngine.self, forPrimaryKey: keywordEngineType) else {
print("Contact \(keywordEngineType) not found")
return
}
try realm.write() {
print("KEYWORD COUNT DAO :: \(keywords.count)")
keywordEngine.keywords.append(objectsIn: keywords)
print("KEYWORD TIMESTAMP UPDATE : \(Date())")
keywordEngine.timestamp = Date()
}
promise(.success(true))
} catch let error as NSError {
print("\(error)")
promise(.failure(error))
}
}
}
- 그렇다면 언제 우리는 Combine Future에 success 신호를 보내야할까?
- 공식 문서에도 안 나와있고 내 나름대로 연구를 했다.
- 우선은 상기의 코드에서 try realm.write의 구간이 모두 끝난 후에 성공신호를 보내면 된다.
- 이유는 하기의 코드와 함께 설명하겠다.
@discardableResult
public func write<Result>(withoutNotifying tokens: [NotificationToken] = [], _ block: (() throws -> Result)) throws -> Result {
beginWrite()
var ret: Result!
do {
ret = try block()
} catch let error {
if isInWriteTransaction { cancelWrite() }
throw error
}
if isInWriteTransaction { try commitWrite(withoutNotifying: tokens) }
return ret
}
- 상기의 코드는 realm의 코드이다.
- realm.write의 클로저에 코드들을 다 담으면
- beginWrite()로 realmDB의 트랜잭션을 시작하고
- commitWrite()로 realmDB를 커밋한다.
- 따라서 write문이 끝나는 시점은 DB입력이 commit이나 cancel이 결정된 상태이다.
- 우리는 그 순간이 바로 약속의 시간 promise(.success(true))를 해야하는 순간이다.
- Error Type도 정해져있으니 Catch 쪽에서는 NSError를 에러 타입으로 캐스팅해줘야한다.