Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/realm #13

Merged
merged 12 commits into from
Nov 16, 2022
200 changes: 186 additions & 14 deletions DailyQuest/DailyQuest.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions DailyQuest/DailyQuest/Data/PersistentStorages/BrowseQuest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// BrowseQuest.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import Foundation

// Domain-Entities 이동
struct BrowseQuest {
let uuid: UUID
let nickName: String
let quests: [Quest]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// BrowseQuestsStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import RxSwift

protocol BrowseQuestsStorage {
func fetchBrowseQuests() -> Observable<[BrowseQuest]>
func saveBrowseQuest(browseQuest: BrowseQuest) -> Single<BrowseQuest>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// BrowseQuestEntity+Mapping.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import Foundation

extension BrowseQuestEntity {
convenience init(browseQuest: BrowseQuest) {
let questsEntities = browseQuest.quests.compactMap { UserQuestEntity(quest: $0) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ΄λ ‡κ²Œλ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€!

Suggested change
let questsEntities = browseQuest.quests.compactMap { UserQuestEntity(quest: $0) }
let questsEntities = browseQuest.quests.compactMap(UserQuestEntity(quest:))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ§„μ›…λ‹˜μ΄ μ•Œλ €μ£Όμ‹  방법이 더 κΉ”λ”ν•΄λ³΄μ΄λ„€μš” λ¦¬νŒ©ν† λ§ λΈŒλžœμΉ˜νŒŒμ„œ Assertionμ΄λž‘ 같이 κ³ μ³λ³΄κ² μŠ΅λ‹ˆλ‹€

self.init(uuid: browseQuest.uuid,
nickName: browseQuest.nickName,
quests: questsEntities)
}
}

extension BrowseQuestEntity {
func toDomain() -> BrowseQuest {
let quests = Array(quests).compactMap { $0.toDomain() }
return BrowseQuest(uuid: uuid,
nickName: nickName,
quests: quests)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// RealmBrowseQuestsStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import RxSwift

final class RealmBrowseQuestsStorage {

private let realmStorage: RealmStorage

init(realmStorage: RealmStorage = RealmStorage.shared) {
self.realmStorage = realmStorage
}
}

extension RealmBrowseQuestsStorage: BrowseQuestsStorage {
func fetchBrowseQuests() -> Observable<[BrowseQuest]> {
return Observable<[BrowseQuest]>.create { [weak self] observer in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
Comment on lines +22 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertion μ—λŸ¬λ₯Ό λ„μ›Œμ£Όλ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€. 비둝 앱이 μ£½μ§€λ§Œ, κ°œλ°œν•˜λŠ” λ™μ•ˆμ—λŠ” ν™•μ‹€ν•œ indicateλ₯Ό 받을 수 μžˆμ„ 것 κ°™μ•„μš” :)

Suggested change
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
guard let realmStorage = self?.realmStorage else {
assertionFailure("realm storage is not exist")
return Disposables.create()

}

do {
let browseQuests = try realmStorage.fetchEntities(type: BrowseQuestEntity.self)
.compactMap { $0.toDomain() }
observer.onNext(browseQuests)
observer.onCompleted()
} catch let error {
observer.onError(error)
}

return Disposables.create()
}
}

func saveBrowseQuest(browseQuest: BrowseQuest) -> Single<BrowseQuest> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

let browseQuestEntity = BrowseQuestEntity(browseQuest: browseQuest)

do {
try realmStorage.updateEntity(entity: browseQuestEntity)
single(.success(browseQuest))
} catch let error {
single(.failure(RealmStorageError.saveError(error)))
}

return Disposables.create()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// BrowseQuestEntity.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import Foundation
import RealmSwift

final class BrowseQuestEntity: Object {
@Persisted var uuid: UUID
@Persisted var nickName: String
@Persisted var quests: List<UserQuestEntity>

override init() { }

init(uuid: UUID, nickName: String, quests: [UserQuestEntity]) {
self.uuid = uuid
self.nickName = nickName
let realmList = List<UserQuestEntity>()
realmList.append(objectsIn: quests)
self.quests = realmList
}

override class func primaryKey() -> String? {
"uuid"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// UserInfoEntity.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import Foundation
import RealmSwift

final class UserInfoEntity: Object {
@Persisted var uuid: UUID
@Persisted var nickName: String
@Persisted var profile: Data
@Persisted var backgroundImage: Data
@Persisted var userDescription: String

override init() { }

init(uuid: UUID, nickName: String, profile: Data, backgroundImage: Data, description: String) {
self.uuid = uuid
self.nickName = nickName
self.profile = profile
self.backgroundImage = backgroundImage
self.userDescription = description
}

override class func primaryKey() -> String? {
"uuid"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// UserQuestEntity.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/14.
//

import Foundation
import RealmSwift

final class UserQuestEntity: Object {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final ν‚€μ›Œλ“œλ‘œ μ„±λŠ₯ν–₯상 μ’‹μ•„μš” ~ :)

@Persisted var uuid: UUID
@Persisted var title: String
@Persisted var startDay: Date
@Persisted var endDay: Date
@Persisted var `repeat`: Int
@Persisted var currentCount: Int
@Persisted var totalCount: Int

override init() { }

init(uuid: UUID, title: String, startDay: Date, endDay: Date, currentCount: Int, totalCount: Int) {
self.uuid = uuid
self.title = title
self.startDay = startDay
self.endDay = endDay
self.currentCount = currentCount
self.totalCount = totalCount
}

override class func primaryKey() -> String? {
"uuid"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// RealmStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/14.
//

import RealmSwift
import Foundation

enum RealmStorageError: Error {
case realmObjectError
case noDataError
case readError(Error)
case saveError(Error)
case deleteError(Error)
}

final class RealmStorage {
static let shared = RealmStorage()

private init() {
// Realm file path
print(Realm.Configuration.defaultConfiguration.fileURL!)
}

private let persistentContainer = try? Realm()

func updateEntity(entity: Object) throws {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
try persistentContainer.write {
persistentContainer.add(entity)
}
}

func fetchEntities<O: Object>(type: O.Type) throws -> [O] {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
return Array(persistentContainer.objects(type))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// UserInfoEntity+Mapping.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import Foundation

// DomainObject -> RealmObject
extension UserInfoEntity {
convenience init(user: User) {
self.init(uuid: user.uuid,
nickName: user.nickName,
profile: user.profile,
backgroundImage: user.backgroundImage,
description: user.description)
}
}

// RealmObject -> DomainObject
extension UserInfoEntity {
func toDomain() -> User {
return User(uuid: uuid,
nickName: nickName,
profile: profile,
backgroundImage: backgroundImage,
description: description)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// RealmUserInfoStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import RxSwift

final class RealmUserInfoStorage {

private let realmStorage: RealmStorage

init(realmStorage: RealmStorage = RealmStorage.shared) {
self.realmStorage = realmStorage
}
}

extension RealmUserInfoStorage: UserInfoStorage {
func fetchUserInfo() -> Observable<User> {
return Observable<User>.create { [weak self] observer in
guard let realmStorage = self?.realmStorage else {
// selfκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ„ 경우, λ°˜ν™˜ν•˜μ§€ μ•Šκ³  μ’…λ£Œ
return Disposables.create()
}

do {
guard let userInfoEntity = try realmStorage.fetchEntities(type: UserInfoEntity.self)
.first else {
throw RealmStorageError.noDataError
}

observer.onNext(userInfoEntity.toDomain())
observer.onCompleted()
} catch let error {
// Realm을 뢈러올 수 없을 경우, realmObjectError
// User 정보가 없을 경우, noDataError
observer.onError(error)
}

return Disposables.create()
}
}

func saveUserInfo(user: User) -> Single<User> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

let userInfo = UserInfoEntity(user: user)

do {
// update μ„±κ³΅ν–ˆμ„ 경우, success(user)
try realmStorage.updateEntity(entity: userInfo)
single(.success(user))
} catch let error {
// update μ„±κ³΅ν•˜μ§€ λͺ»ν–ˆμ„ 경우, failure(error)
single(.failure(RealmStorageError.saveError(error)))
}

return Disposables.create()
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// UserInfoStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/15.
//

import RxSwift

protocol UserInfoStorage {
func fetchUserInfo() -> Observable<User>
func saveUserInfo(user: User) -> Single<User>
}
Loading