Skip to content

Commit

Permalink
Merge pull request #149 from JUDA-Hrmi/refactoring/Post
Browse files Browse the repository at this point in the history
[Edit] Post 및 Drink  ViewModel 및 Service 파일 로직 수정중 #142
  • Loading branch information
bdrsky2010 authored Mar 8, 2024
2 parents f449c05 + 9a8d909 commit 84afa90
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 43 deletions.
24 changes: 16 additions & 8 deletions JUDA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@
7B6D76B32B67D3B700601B55 /* PostDrinkRating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76B22B67D3B700601B55 /* PostDrinkRating.swift */; };
7B6D76B52B67D5F900601B55 /* PostTags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76B42B67D5F900601B55 /* PostTags.swift */; };
7B6D76B92B68D9C900601B55 /* PostReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76B82B68D9C900601B55 /* PostReportView.swift */; };
7B881CA32B97464200571352 /* FirestorePostViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881CA22B97464200571352 /* FirestorePostViewModel.swift */; };
7B881CA52B97545700571352 /* FirestoreDrinkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881CA42B97545700571352 /* FirestoreDrinkViewModel.swift */; };
7B74FA5B2B9A9EE800BAC2AC /* PostViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B74FA5A2B9A9EE800BAC2AC /* PostViewModel.swift */; };
7B74FA5D2B9ABF7600BAC2AC /* RecordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B74FA5C2B9ABF7600BAC2AC /* RecordViewModel.swift */; };
7B881CA32B97464200571352 /* FirestorePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881CA22B97464200571352 /* FirestorePostService.swift */; };
7B881CA52B97545700571352 /* FirestoreDrinkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881CA42B97545700571352 /* FirestoreDrinkService.swift */; };
7B904C662B6168C60052384A /* PostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B904C652B6168C60052384A /* PostCell.swift */; };
7B904C682B6184560052384A /* CustomTextSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B904C672B6184560052384A /* CustomTextSegment.swift */; };
7B92656B2B692E7200840095 /* PostReportTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B92656A2B692E7200840095 /* PostReportTitle.swift */; };
Expand Down Expand Up @@ -265,8 +267,10 @@
7B6D76B42B67D5F900601B55 /* PostTags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTags.swift; sourceTree = "<group>"; };
7B6D76B62B68972000601B55 /* PostGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostGrid.swift; sourceTree = "<group>"; };
7B6D76B82B68D9C900601B55 /* PostReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostReportView.swift; sourceTree = "<group>"; };
7B881CA22B97464200571352 /* FirestorePostViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirestorePostViewModel.swift; sourceTree = "<group>"; };
7B881CA42B97545700571352 /* FirestoreDrinkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirestoreDrinkViewModel.swift; sourceTree = "<group>"; };
7B74FA5A2B9A9EE800BAC2AC /* PostViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewModel.swift; sourceTree = "<group>"; };
7B74FA5C2B9ABF7600BAC2AC /* RecordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordViewModel.swift; sourceTree = "<group>"; };
7B881CA22B97464200571352 /* FirestorePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirestorePostService.swift; sourceTree = "<group>"; };
7B881CA42B97545700571352 /* FirestoreDrinkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirestoreDrinkService.swift; sourceTree = "<group>"; };
7B904C652B6168C60052384A /* PostCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCell.swift; sourceTree = "<group>"; };
7B904C672B6184560052384A /* CustomTextSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextSegment.swift; sourceTree = "<group>"; };
7B92656A2B692E7200840095 /* PostReportTitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostReportTitle.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -729,8 +733,10 @@
children = (
B1EE249B2B6144CD007F68B0 /* PostsViewModel.swift */,
7B0A8BC82B8C88F300740E61 /* SearchPostsViewModel.swift */,
7B881CA22B97464200571352 /* FirestorePostViewModel.swift */,
7B881CA42B97545700571352 /* FirestoreDrinkViewModel.swift */,
7B881CA22B97464200571352 /* FirestorePostService.swift */,
7B881CA42B97545700571352 /* FirestoreDrinkService.swift */,
7B74FA5A2B9A9EE800BAC2AC /* PostViewModel.swift */,
7B74FA5C2B9ABF7600BAC2AC /* RecordViewModel.swift */,
);
path = Posts;
sourceTree = "<group>";
Expand Down Expand Up @@ -899,6 +905,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7B74FA5B2B9A9EE800BAC2AC /* PostViewModel.swift in Sources */,
0974A1542B8B84E900476199 /* ShimmerDrinkListCell.swift in Sources */,
0902EB492B7E3372003D555E /* ProfileSettingView.swift in Sources */,
095D708D2B98200B00F76C11 /* FirebaseUserViewModel.swift in Sources */,
Expand All @@ -908,7 +915,8 @@
7BBDFF6F2B6B90EB0036FB8B /* AddTagView.swift in Sources */,
09A320162B8B30D100DE4646 /* SearchDrinkViewModel.swift in Sources */,
7BBDFF702B6B90EB0036FB8B /* PostGrid.swift in Sources */,
7B881CA52B97545700571352 /* FirestoreDrinkViewModel.swift in Sources */,
7B74FA5D2B9ABF7600BAC2AC /* RecordViewModel.swift in Sources */,
7B881CA52B97545700571352 /* FirestoreDrinkService.swift in Sources */,
090FF1CE2B83413100AF22B5 /* CustomLoadingView.swift in Sources */,
2C5B0F422B6B10CF005F1A99 /* CustomDialog.swift in Sources */,
AC588E862B8CC8F10063AAB0 /* AIWellMatchViewModel.swift in Sources */,
Expand All @@ -929,7 +937,7 @@
09A6AD722B70B46E00606585 /* AppViewModel.swift in Sources */,
7B6D76B32B67D3B700601B55 /* PostDrinkRating.swift in Sources */,
7B6D76B12B67D1E100601B55 /* PostPhotoScroll.swift in Sources */,
7B881CA32B97464200571352 /* FirestorePostViewModel.swift in Sources */,
7B881CA32B97464200571352 /* FirestorePostService.swift in Sources */,
0974A1502B8B7B6C00476199 /* ShimmerPostCell.swift in Sources */,
09F869B52B6A47B700A56A4C /* AlarmStoreListCell.swift in Sources */,
B1EE249A2B6144C5007F68B0 /* RecordViewModel.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ enum DrinkFetchError: Error {
}

@MainActor
final class FirestoreDrinkViewModel {
private let firestorePostViewModel = FirestorePostViewModel()
final class FirestoreDrinkService {
private let firestorePostService = FirestorePostService()
}

// MARK: Firestore Fetch Data
extension FirestoreDrinkViewModel {
extension FirestoreDrinkService {
// drinks collection의 document data 불러오는 메서드
// 불러오지 못 할 경우 error를 throw
func fetchDrinkDocument(ref: CollectionReference, drinkID: String) async throws -> Drink {
func fetchDrinkDocument(document: DocumentReference) async throws -> Drink {
do {
let taggedPostsRef = ref.document(drinkID).collection("taggedPosts")
let agePreferenceUIDRef = ref.document(drinkID).collection("agePreferenceUID")
let genderPreferenceUIDRef = ref.document(drinkID).collection("genderPreferenceUID")
let likedUsersIDRef = ref.document(drinkID).collection("likedUsersID")
let taggedPostsRef = document.collection("taggedPosts")
let agePreferenceUIDRef = document.collection("agePreferenceUID")
let genderPreferenceUIDRef = document.collection("genderPreferenceUID")
let likedUsersIDRef = document.collection("likedUsersID")

let drikField = try await fetchDrinkField(ref: ref, drinkID: drinkID)
let drikField = try await fetchDrinkField(document: document)
let taggedPosts = await fetchTaggedPosts(ref: taggedPostsRef)
let agePreference = await fetchAgePreferenceUID(ref: agePreferenceUIDRef)
let genderPreference = await fetchGenderPreferenceUID(ref: genderPreferenceUIDRef)
Expand Down Expand Up @@ -66,7 +66,7 @@ extension FirestoreDrinkViewModel {
let snapshot = try await ref.getDocuments()
for document in snapshot.documents {
let documentRef = document.reference
let taggedPost = try await firestorePostViewModel.fetchPostDocument(document: documentRef)
let taggedPost = try await firestorePostService.fetchPostDocument(document: documentRef)

taggedPosts.append(taggedPost)
}
Expand All @@ -79,9 +79,9 @@ extension FirestoreDrinkViewModel {

// drinks collection의 Field data 불러오는 메서드
// 불러오지 못 할 경우 error를 throw
func fetchDrinkField(ref: CollectionReference, drinkID: String) async throws -> DrinkField {
func fetchDrinkField(document: DocumentReference) async throws -> DrinkField {
do {
return try await ref.document(drinkID).getDocument(as: DrinkField.self)
return try await document.getDocument(as: DrinkField.self)
} catch {
print(error.localizedDescription)
throw DrinkFetchError.drinkField
Expand Down Expand Up @@ -154,7 +154,7 @@ extension FirestoreDrinkViewModel {
}

// MARK: Firestore drink field data update
extension FirestoreDrinkViewModel {
extension FirestoreDrinkService {
// drinks collection field data update 메서드
func updateDrinkField(ref: CollectionReference, drinkID: String, data: [String: Any]) async -> Bool {
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import Foundation
import FirebaseCore
import FirebaseFirestore

enum PostFetchError: Error {
case postField, postDocument
enum PostError: Error {
case fieldFetch, documentFetch, upload, update, delete
}

@MainActor
final class FirestorePostViewModel {}
final class FirestorePostService {}

// MARK: Firestore Fetch Data
extension FirestorePostViewModel {
extension FirestorePostService {
// posts collection의 post document data 불러오는 메서드
// 불러오지 못 할 수 경우 error throw
func fetchPostDocument(document: DocumentReference) async throws -> Post {
Expand All @@ -27,12 +27,12 @@ extension FirestorePostViewModel {
let likedUsersID: [String] = await fetchPostLikedUsersID(ref: likedUsersIDRef)

return Post(postField: postField, likedUsersID: likedUsersID)
} catch PostFetchError.postField {
print("error :: fetchPostField() -> fetch post field data failure")
throw PostFetchError.postField
} catch PostError.fieldFetch {
// print("error :: fetchPostField() -> fetch post field data failure")
throw PostError.fieldFetch
} catch {
print("error :: fetchPostDocument() -> fetch post document data failure")
throw PostFetchError.postDocument
// print("error :: fetchPostDocument() -> fetch post document data failure")
throw PostError.documentFetch
}
}

Expand All @@ -43,7 +43,7 @@ extension FirestorePostViewModel {
return try await document.getDocument(as: PostField.self)
} catch {
print(error.localizedDescription)
throw PostFetchError.postField
throw PostError.fieldFetch
}
}

Expand All @@ -66,34 +66,58 @@ extension FirestorePostViewModel {
}
}

//MARK: Firestore post document upload
extension FirestorePostService {
func uploadPostDocument(post: Post) async throws {
let postID = UUID().uuidString
let postDocumentRef = Firestore.firestore().collection("posts").document(postID)
let likedUsersIDCollectionRef = postDocumentRef.collection("likedUsersID")

do {
try postDocumentRef.setData(from: post.postField, merge: true)
for userID in post.likedUsersID {
do {
try await likedUsersIDCollectionRef.document(userID).setData([:])
} catch {
print("error :: uploadPostDocument() -> upload post likedUsersID collection data failure")
print(error.localizedDescription)
// continue
}
}
} catch {
print("error :: uploadPostDocument() -> upload post document data failure")
print(error.localizedDescription)
throw PostError.upload
}
}
}

// MARK: Firestore post document delete
extension FirestorePostViewModel {
extension FirestorePostService {
// posts collection에서 삭제하고싶은 post에 해당하는 document 삭제 메서드
func deletePostDocument(postID: String) async -> Bool {
let postRef = Firestore.firestore().collection("posts")
func deletePostDocument(postID: String) async throws {
let postsRef = Firestore.firestore().collection("posts")

do {
try await postRef.document(postID).delete()
return true
try await postsRef.document(postID).delete()
} catch {
print("error :: postDelete() -> delete post document data failure")
print("error :: deletePostDocument() -> delete post document data failure")
print(error.localizedDescription)
return false
throw PostError.delete
}
}
}

// MARK: Firestore post field data update
extension FirestorePostViewModel {
extension FirestorePostService {
// posts collection에서 수정하고싶은 post에 해당하는 field data 업데이트 메서드
func updatePostField(ref: CollectionReference, postID: String, data: [String: Any]) async -> Bool {
func updatePostField(ref: CollectionReference, postID: String, data: [String: Any]) async throws {
do {
try await ref.document(postID).updateData(data)
return true
} catch {
print("error :: postFieldUpdate() -> update post field data failure")
print("error :: updatePostField() -> update post field data failure")
print(error.localizedDescription)
return false
throw PostError.update
}
}
}
103 changes: 103 additions & 0 deletions JUDA/ViewModel/Posts/PostViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// PostService.swift
// JUDA
//
// Created by Minjae Kim on 3/8/24.
//

import SwiftUI
import FirebaseFirestore

@MainActor
final class PostViewModel: ObservableObject {
// 파이어베이스 연결
private let db = Firestore.firestore()
private let firestorePostService = FirestorePostService()
private let firestoreDrinkService = FirestoreDrinkService()

// 게시글 객체 배열
@Published var posts = [Post]()
// 마지막 포스트 확인용(페이징)
@Published var lastQuerydocumentSnapshot: QueryDocumentSnapshot?
// 게시글 불러오기 또는 삭제 작업이 진행중인지 나타내는 상태 프로퍼티
@Published var isLoading = false
}

// MARK: Fetch
extension PostViewModel {
func getPostSortType(postSortType: PostSortType) -> Query {
let postRef = db.collection("posts")

switch postSortType {
case .popularity:
return postRef.order(by: "likedCount", descending: true)
case .mostRecent:
return postRef.order(by: "postedTimeStamp", descending: true)
}
}

func firstFetchPost(query: Query) async {
do {
let firstSnapshot = try await query.limit(to: 20).getDocuments()
lastQuerydocumentSnapshot = firstSnapshot.documents.last
isLoading = true
await fetchPosts(querySnapshots: firstSnapshot)
} catch {
print("posts paging fetch error \(error.localizedDescription)")
}
}

func nextFetchPost(query: Query) async {
guard let lastQuerydocumentSnapshot = lastQuerydocumentSnapshot else { return }
do {
let nextSnapshot = try await query.limit(to: 20).start(afterDocument: lastQuerydocumentSnapshot).getDocuments()
self.lastQuerydocumentSnapshot = nextSnapshot.documents.last
await fetchPosts(querySnapshots: nextSnapshot)
} catch {
print("posts paging fetch error \(error.localizedDescription)")
}
}

func fetchPosts(querySnapshots: QuerySnapshot) async {
var tasks: [Task<(Int, Post)?, Error>] = []
let postRef = db.collection("posts")

for (index, document) in querySnapshots.documents.enumerated() {
let task = Task<(Int, Post)?, Error> {
do {
let post = try await firestorePostService.fetchPostDocument(document: document.reference)
return (index, post)
} catch PostError.fieldFetch {
print("error :: fetchPostField() -> fetch post field data failure")
return nil
} catch PostError.documentFetch {
print("error :: fetchPostDocument() -> fetch post document data failure")
return nil
}
}
tasks.append(task)
}

var results = [(Int, Post)]()
for task in tasks {
do {
if let result = try await task.value {
results.append(result)
}
} catch {
print(error.localizedDescription)
}
}
results.sort { $0.0 < $1.0 }

let posts = results.map { $0.1 }

self.posts.append(contentsOf: posts)
self.isLoading = false
}
}

// MARK: delete
extension PostViewModel {

}
8 changes: 8 additions & 0 deletions JUDA/ViewModel/Posts/RecordViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// RecordService.swift
// JUDA
//
// Created by Minjae Kim on 3/8/24.
//

import Foundation

0 comments on commit 84afa90

Please sign in to comment.