Long Hang Times When Accessing View With Posts

For some reason, every time I'm accessing a view populated with posts and fetching posts, my app has like a 5-8 second hang time. I don't know whats causing this issue, and I have been dealing with this for 3 days.

`func fetchPosts(completion: @escaping (Result<[PostWithUser], Error>) -> Void) { if !cachedPosts.isEmpty { completion(.success(self.cachedPosts)) return }

    postsRef.order(by: "timestamp", descending: true).getDocuments { [weak self] snapshot, error in
        guard let self = self else { return }
        
        if let error = error {
            completion(.failure(error))
            return
        }
        
        guard let documents = snapshot?.documents else {
            completion(.success([]))
            return
        }
        
        let group = DispatchGroup()
        var postsWithUsers: [PostWithUser] = []
        
        DispatchQueue.global(qos: .userInitiated).async {
            for document in documents {
                group.enter()
                let data = document.data()
                guard let userId = data["userId"] as? String,
                      let parentId = data["parentId"] as? String,
                      let groupId = data["groupId"] as? String,
                      let text = data["text"] as? String,
                      let isPinned = data["isPinned"] as? Bool,
                      let imageUrl = data["imageUrl"] as? String,
                      let videoUrl = data["videoUrl"] as? String,
                      let timestamp = data["timestamp"] as? Timestamp,
                      let views = data["views"] as? Int else {
                    group.leave()
                    continue
                }
                
                let post = Post(id: document.documentID, userId: userId, parentId: parentId, groupId: groupId, text: text, imageUrl: imageUrl, videoUrl: videoUrl, timestamp: timestamp.dateValue(), isPinned: isPinned, likedBy: [], views: views)
                
                self.usersRef.document(userId).getDocument { userDocument, error in
                    defer { group.leave() }
                    
                    if let userDocument = userDocument, let userData = userDocument.data() {
                        let user = User(
                            id: userId,
                            username: userData["username"] as? String ?? "",
                            bio: userData["bio"] as? String ?? "",
                            profilePictureUrl: userData["profileImageUrl"] as? String ?? "",
                            privateProfile: userData["privateProfile"] as? Bool ?? false,
                            privateFollowerList: userData["privateFollowerList"] as? Bool ?? false,
                            privateFollowingList: userData["privateFollowingList"] as? Bool ?? false,
                            privateReplies: userData["privateReplies"] as? Bool ?? false,
                            privateLikes: userData["privateLikes"] as? Bool ?? false
                        )
                        let postWithUser = PostWithUser(post: post, user: user)
                        
                        DispatchQueue.main.async {
                            postsWithUsers.append(postWithUser)
                        }
                    } else {
                        print("Failed to fetch user data for userId: \(userId), error: \(String(describing: error))")
                    }
                }
            }
            
            group.notify(queue: .main) {
                self.cachedPosts = postsWithUsers
                completion(.success(postsWithUsers))
            }
        }
    }
}`

`

func fetchPosts() {
    PostService.shared.fetchPosts { result in
        switch result {
        case .success(let posts):
            DispatchQueue.main.async {
                self.posts = posts
            }
        case .failure(let error):
            print("Failed to fetch posts: \(error)")
        }
    }
}

func refreshPosts() {
    PostService.shared.refreshPosts { result in
        switch result {
        case .success(let posts):
            DispatchQueue.main.async {
                self.posts = posts
            }
        case .failure(let error):
            print("Failed to fetch posts: \(error)")
        }
    }
}

Not sure but you should add some print in your code to see when all your closures execute as you seem to always change queue even when you already are in the same queue. You may do the fetch on main queue or block it from other thread.

Long Hang Times When Accessing View With Posts
 
 
Q