为什么我每次调用fetchfollowingposts,帖子用户都变了?

问题描述 投票:0回答:0

只要调用“fetchfollowingposts”函数,提要单元格中的用户信息就会发生变化。我已经使用用户的 uid 将帖子保存到 firebase,并且我正在尝试从绑定到帖子的 uid 中获取他们的个人资料照片、全名等。每当我刷新提要视图时,用户的信息都会发生变化,但帖子本身永远不会改变(时间戳、帖子标题、帖子图片、喜欢)。

因为我不完全理解这个问题,所以我不确定需要什么文件,所以如果我错过了一个,请告诉我。预先感谢您的帮助!

FeedCellView

import SwiftUI
import Kingfisher

struct FeedCell: View {
    @ObservedObject var viewModel: FeedCellViewModel
    @State private var isShowingBottomSheet = false
    var didLike: Bool { return viewModel.post.didLike ?? false }
    @Environment(\.presentationMode) var mode
    
    init(viewModel: FeedCellViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {
        
        VStack (alignment: .leading, spacing: 16) {
            
            NavigationLink {
                if let user = viewModel.post.user {
                    LazyView(ProfileView(user: user))
                }
            } label: {
                HStack (alignment: .top) {
                    KFImage(URL(string: viewModel.post.user?.profileImageUrl ?? "https://firebasestorage.googleapis.com/v0/b/pageturner-951b4.appspot.com/o/profile_image%2FNoProfilePhoto.png?alt=media&token=1055648d-4d6e-4d51-b003-948a47b6bb76"))
                        .resizable()
                        .scaledToFill()
                        .frame(width: 48, height: 48)
                        .cornerRadius(10)
                    VStack (alignment: .leading, spacing: 4) {
                        Text(viewModel.post.user?.fullname ?? "")
                            .font(.system(size: 16))
                            .foregroundColor(Color(.label))
                        Text(viewModel.timestampString)
                            .font(.system(size: 14))
                            .foregroundColor(.gray)
                    }
                    Spacer()
                    
                    if viewModel.post.isCurrentUser {
                        Button {
                            isShowingBottomSheet.toggle()
                        } label: {
                            Image(systemName: "ellipsis")
                        }.foregroundColor(Color(.gray))
                            .confirmationDialog("What do you want to do?",
                                                isPresented: $isShowingBottomSheet) {
                                Button("Delete post", role: .destructive) {
                                    viewModel.deletePost()
                                }
                            } message: {
                                Text("You cannot undo this action")
                            }
                    }
                }
            }
            
            Text(viewModel.post.caption)
                .font(.system(size: 16))
            
            if let image = viewModel.post.imageUrl {
                KFImage(URL(string: image))
                    .resizable()
                    .scaledToFill()
                    .frame(maxHeight: 250)
                    .cornerRadius(10)
            }
            HStack {
                HStack (spacing: 24) {
                    Button {
                        didLike ? viewModel.unlike() : viewModel.like()
                    } label: {
                        Image(didLike ? "heart.fill" : "heart")
                            .renderingMode(.template)
                            .resizable()
                            .foregroundColor(didLike ? Color.accentColor : .black)
                            .frame(width: 24, height: 24)
                        Text("\(viewModel.post.likes)")
                    }
                    NavigationLink {
                        CommentView(post: viewModel.post)
                    } label: {
                        Image("comment")
                            .renderingMode(.template)
                            .resizable()
                            .frame(width: 24, height: 24)
                        Text("\(viewModel.post.stats?.CommentCount ?? 0)")
                    }
                }
                Spacer()
            }
            .foregroundColor(Color(.label))
        }
    }
}

FeedService

import SwiftUI
import FirebaseCore
import FirebaseAuth
import FirebaseFirestore
import FirebaseFirestoreSwift

struct FeedService {
    
    func uploadPost(caption: String, image: UIImage?, completion: @escaping(Bool) -> Void) {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        ImageUploader.uploadImage(image: image, type: .post) { imageUrl in
            let data = ["uid": uid,
                        "caption": caption,
                        "likes": 0,
                        "imageUrl": imageUrl,
                        "timestamp": Timestamp(date: Date())] as [String: Any]
            
            COLLECTION_POSTS.document()
                .setData(data) { error in
                    if let error = error {
                        print("DEBUG: Failed to upload post with error: \(error.localizedDescription)")
                        completion(false)
                        return
                    }
                }
            completion(true)
        }
    }
    
    func fetchFollowingPosts(forUid uid: String, completion: @escaping([Post]) -> Void) {
        var posts = [Post]()
        
        COLLECTION_FOLLOWING.document(uid).collection("user-following")
            .getDocuments { snapshot, _ in
                guard let documents = snapshot?.documents else { return }
                
                documents.forEach { doc in
                    let userId = doc.documentID
                    
                    COLLECTION_POSTS.whereField("uid", isEqualTo: userId)
                        .getDocuments { snapshot, _ in
                            guard let documents = snapshot?.documents else { return }
                            let post = documents.compactMap({ try? $0.data(as: Post.self) })
                            posts.append(contentsOf: post)
                            
                            completion(posts.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue()
                            }))
                        }
                }
            }
    }
    
    func uploadStory(caption: String?, image: UIImage, rating: Int?, completion: @escaping(Bool) -> Void) {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        
        ImageUploader.uploadImage(image: image, type: .story) { imageUrl in
            let data = ["uid": uid,
                        "caption": caption ?? "",
                        "imageUrl": imageUrl,
                        "rating": rating ?? "",
                        "isSeen": false,
                        "timestamp": Timestamp(date: Date())] as [String: Any]
            
            COLLECTION_STORIES.document()
                .setData(data) { error in
                    if let error = error {
                        print("DEBUG: Failed to upload story with error: \(error.localizedDescription)")
                        completion(false)
                        return
                    }
                }
            completion(true)
        }
    }
    
    func fetchFollowingStories(forUid uid: String, completion: @escaping([Story]) -> Void) {
        var stories = [Story]()
        
        COLLECTION_FOLLOWING.document(uid).collection("user-following")
            .getDocuments { snapshot, _ in
                guard let documents = snapshot?.documents else { return }
                
                documents.forEach { doc in
                    let userId = doc.documentID
                    
                    COLLECTION_STORIES.whereField("uid", isEqualTo: userId)
                        .getDocuments { snapshot, _ in
                            guard let documents = snapshot?.documents else { return }
                            let story = documents.compactMap({ try? $0.data(as: Story.self) })
                            stories.append(contentsOf: story)
                            
                            completion(stories.sorted(by: { $0.timestamp.dateValue() > $1.timestamp.dateValue()
                            }))
                        }
                }
            }
    }
}

FeedViewModel

import SwiftUI

class FeedViewModel: ObservableObject {
    @Published var followingPosts = [Post]()
    @Published var followingStories = [Story]()
    let service = FeedService()
    let userService = UserService()
    
    init() {
        fetchFollowingPosts()
        fetchFollowingStories()
    }
    
    func fetchFollowingPosts() {
        
        guard let userid = AuthViewModel.shared.userSession?.uid else { return }
        
        service.fetchFollowingPosts(forUid: userid) { posts in
            self.followingPosts = posts
            
            for i in 0 ..< posts.count {
                let uid = posts[i].uid
                
                self.userService.fetchUser(withUid: uid) { user in
                    self.followingPosts[i].user = user
               }
            }
        }
    }
    
    func fetchFollowingStories() {
        
        guard let userid = AuthViewModel.shared.userSession?.uid else { return }
        
        service.fetchFollowingStories(forUid: userid) { stories in
            self.followingStories = stories
            
            for i in 0 ..< stories.count {
                let uid = stories[i].uid
                
                self.userService.fetchUser(withUid: uid) { user in
                    self.followingStories[i].user = user
               }
            }
        }
    }
} 
swift google-cloud-firestore
© www.soinside.com 2019 - 2024. All rights reserved.