Every time I navigate to a view populated with posts, it’s very slow. My social network platform has a lot of posts, and I need more efficient data management for fetching the posts.
Is there any part of the code that should be changed or removed?
func fetchPosts(completion: @escaping (Result<[PostWithUser], Error>) -> Void) {
DispatchQueue.global(qos: .background).async { [weak self] in
guard let self = self else { return }
if !self.cachedPosts.isEmpty {
DispatchQueue.main.async {
completion(.success(self.cachedPosts))
}
return
}
self.postsRef.order(by: "timestamp", descending: true).getDocuments { snapshot, error in
if let error = error {
DispatchQueue.main.async {
completion(.failure(error))
}
return
}
guard let documents = snapshot?.documents else {
DispatchQueue.main.async {
completion(.success([]))
}
return
}
let group = DispatchGroup()
var postsWithUsers: [PostWithUser] = []
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,
accountDeactivated: userData["accountDeactivated"] 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))
}
}
}
}
I tried changing the threading but I didn’t notice any changes.