Saturday, June 22, 2024
HomeiOS Developmentios - When navigating to the house view, it takes a very...

ios – When navigating to the house view, it takes a very long time to load, and when navigating again from the FullPostCell, it takes seconds to navigate again


The Residence View (or any view with posts populated) could be very gradual, and after debugging, I discovered that the filtering was NOT inflicting the issue. For some cause, it is not gradual on the simulator, however on an precise gadget it is vitally gradual, particularly after posts loading.
I additionally debugged a bunch of occasions, and I am nonetheless unable to determine this downside, nothing within the debugs displaying what’s inflicting it, however my guess is its a bottlenecking downside.

import SwiftUI

struct HomeView: View {
    @EnvironmentObject var authViewModel: AuthViewModel
    @StateObject var viewModel = PostViewModel()
    @StateObject var followingViewModel = FollowingViewModel()
    @StateObject var followViewModel = FollowViewModel()
    @StateObject var profileViewModel = ProfileViewModel()
    @StateObject var likeViewModel = LikeViewModel()
    @StateObject var appData: AppData
    @State non-public var selectedHomeTab: Int = 0
    @State non-public var isLoading: Bool = true
    @State non-public var lastViewedPostId: String? {
        didSet {
            if let id = lastViewedPostId {
                UserDefaults.normal.set(id, forKey: "lastViewedPostId")
            }
        }
    }
    var physique: some View {
        VStack {
            ToolbarModifier(viewTitle: .fixed("Residence"), appData: appData)
            VStack {
                HStack(spacing: 87) {
                    Textual content("For You")
                        .foregroundStyle(selectedHomeTab == 0 ? Coloration.black : Coloration.grey)
                        .font(.system(measurement: 15, weight: .semibold))
                        .offset(y: 10)
                        .onTapGesture {
                            withAnimation(.easeIn(length: 0.2)) {
                                selectedHomeTab = 0
                            }
                        }
                    Textual content("Following")
                        .foregroundStyle(selectedHomeTab == 1 ? Coloration.black : Coloration.grey)
                        .font(.system(measurement: 15, weight: .semibold))
                        .offset(y: 10)
                        .onTapGesture {
                            withAnimation(.easeIn(length: 0.2)) {
                                selectedHomeTab = 1
                            }
                        }
                }
                Rectangle()
                    .body(width: 50, peak: 5)
                    .foregroundStyle(Coloration(hex: "#5CE1E6"))
                    .cornerRadius(3)
                    .offset(x: selectedHomeTab == 0 ? -77.4 : 70.2, y: 7)
            }
            .animation(.easeIn(length: 0.1), worth: selectedHomeTab)
            .padding(.high, 3)
            
            TabView(choice: $selectedHomeTab) {
                ScrollViewReader { scrollProxy in
                    ScrollView(showsIndicators: false) {
                        VStack(spacing: 14) {
                            if viewModel.posts.rely > 0 {
                                
                                let viewWeight: Double = 0.5
                                let timestampWeight: Double = 1.2
                                let likesWeight: Double = 0.9
                                
                                let cutoffDate = Calendar.present.date(byAdding: .day, worth: -1, to: Date()) ?? Date()
                                
                                let sortedPosts = viewModel.posts
                                    .lazy
                                    .filter { !$0.consumer.privateProfile && $0.submit.parentId.isEmpty && $0.submit.groupId.isEmpty }
                                    .sorted { (post1, post2) -> Bool in
                                        let likesCount1 = likeViewModel.likes.filter { $0.like.postId == post1.submit.id }.rely
                                        let likesCount2 = likeViewModel.likes.filter { $0.like.postId == post2.submit.id }.rely
                                        
                                        let score1 = Double(post1.submit.views) * viewWeight
                                        + post1.submit.timestamp.timeIntervalSince(cutoffDate) / 3600 * timestampWeight
                                        + Double(likesCount1) * likesWeight
                                        
                                        let score2 = Double(post2.submit.views) * viewWeight
                                        + post2.submit.timestamp.timeIntervalSince(cutoffDate) / 3600 * timestampWeight
                                        + Double(likesCount2) * likesWeight
                                        
                                        return score1 > score2
                                    }
    
                                ForEach(sortedPosts) { submit in
                                    PostCell(postWithUser: submit, appData: appData)
                                        .id(submit.id)
                                        .onAppear {
                                            lastViewedPostId = submit.id
                                        }
                                }
                                .padding(.high, 17)
                                
                            } else {
                                LoadingModifier()
                                    .padding(.high, 230)
                            }
                        }
                    }
                    .tag(0)
                    .onAppear {
                        viewModel.fetchPosts()
                        if let savedId = lastViewedPostId {
                            DispatchQueue.primary.asyncAfter(deadline: .now() + 0.1) {
                                withAnimation(.easeIn) {
                                    scrollProxy.scrollTo(savedId, anchor: .middle)
                                }
                            }
                        }
                    }
                }
                
                ScrollView(showsIndicators: false) {
                    if !isLoading {
                        VStack(spacing: 10) {
                            if viewModel.posts.rely != 0 {
                                let followingPosts = viewModel.posts
                                .filter { $0.submit.parentId.isEmpty && $0.submit.groupId.isEmpty }
                                .filter { postWithUser in
                                    followingViewModel.followings.accommodates { $0.consumer.id == postWithUser.consumer.id }
                                }
                                .sorted(by: { $0.submit.timestamp > $1.submit.timestamp })
                                if !followingPosts.isEmpty {
                                    ForEach(followingPosts, id: .submit.id) { postWithUser in
                                        PostCell(postWithUser: postWithUser, appData: appData)
                                    }
                                    .padding(.high, 17)
                                }
                            } else {
                                Picture(systemName: "individual.fill")
                                    .resizable()
                                    .scaledToFit()
                                    .body(width: 30, peak: 30)
                                    .fontWeight(.daring)
                                    .foregroundStyle(Coloration(UIColor.systemGray2))
                                    .padding(.high, 120)
                                Textual content("Your not following anybody but.")
                                    .foregroundStyle(Coloration(UIColor.systemGray2))
                                    .font(.system(measurement: 16, weight: .semibold))
                                    .padding(.backside)
                                if appData.showFollowRecomendations {
                                    ZStack {
                                        Rectangle()
                                            .foregroundStyle(Coloration(UIColor.systemGray6))
                                            .body(maxWidth: .infinity)
                                            .body(peak: 245)
                                            .cornerRadius(7)
                                            .padding(.horizontal, 16)
                                        VStack(spacing: 7) {
                                            HStack {
                                                Textual content("Continuously adopted")
                                                    .foregroundStyle(Coloration(UIColor.systemGray2))
                                                    .font(.system(measurement: 14, weight: .common))
                                                
                                                Spacer()
                                                
                                                Picture(systemName: "xmark")
                                                    .resizable()
                                                    .scaledToFit()
                                                    .body(width: 14, peak: 14)
                                                    .fontWeight(.daring)
                                                    .foregroundStyle(Coloration(UIColor.systemGray2))
                                                    .onTapGesture {
                                                        appData.showFollowRecomendations = false
                                                    }
                                            }
                                            .padding(.backside, 7)
                                            ForEach(profileViewModel.customers
                                                .sorted(by: { user1, user2 in
                                                    let user1FollowerCount = followViewModel.follows.filter { $0.observe.currentUserId == user1.id }.rely
                                                    let user2FollowerCount = followViewModel.follows.filter { $0.observe.currentUserId == user2.id }.rely
                                                    return user1FollowerCount > user2FollowerCount
                                                }).prefix(3)) { consumer in
                                                    if consumer.id != profileViewModel.id {
                                                        NavigationLink(vacation spot: UserProfileView(consumer: consumer)) {
                                                            ProfileCell(consumer: consumer)
                                                        }
                                                    } else {
                                                        NavigationLink(vacation spot: ProfileView(appData: appData)) {
                                                            ProfileCell(consumer: consumer)
                                                        }
                                                    }
                                                }
                                        }
                                        .padding(.horizontal, 43)
                                    }
                                }
                            }
                        }
                    } else {
                        LoadingModifier()
                            .padding(.high, 80)
                    }
                }
                .tag(1)
                .onAppear {
                    followingViewModel.fetchFollowings()
                    DispatchQueue.primary.asyncAfter(deadline: .now() + 0.2) {
                        isLoading = false
                    }
                }
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .by no means))
            .refreshable {
                viewModel.refreshPosts()
                viewModel.fetchPosts()
                profileViewModel.fetchUsers()
            }
        }
        .navigationBarBackButtonHidden(true)
        .navigationTitle("")
        .onAppear {
            viewModel.fetchPosts()
            profileViewModel.fetchUsers()
            likeViewModel.fetchLikes()
            appData.showMainNavBar = true
            lastViewedPostId = UserDefaults.normal.string(forKey: "lastViewedPostId")
            
        }
    }
}

#Preview {
    HomeView(appData: AppData())
}

import Basis
import SwiftUI
import Firebase

class PostViewModel: ObservableObject {
    @Revealed var posts: [PostWithUser] = []
    
    let db = Firestore.firestore()
    
    @MainActor
    func fetchPosts() {
        PostService.shared.fetchPosts { lead to
            DispatchQueue.primary.async {
                swap outcome {
                case .success(let posts):
                    self.posts = posts
                case .failure(let error):
                    print("Did not fetch posts: (error)")
                }
            }
        }
    }
    
    func refreshPosts() {
        PostService.shared.refreshPosts { lead to
            DispatchQueue.primary.async {
                swap outcome {
                case .success(let posts):
                    self.posts = posts
                case .failure(let error):
                    print("Did not fetch posts: (error)")
                }
            }
        }
    }
    
    non-public func fetchUserProfiles(for posts: [Post]) {
        let userIds = Set(posts.map { $0.userId })
        UserService.shared.fetchUsers(userIds: Array(userIds)) { lead to
            DispatchQueue.primary.async {
                swap outcome {
                case .success(let customers):
                    let userDict = Dictionary(uniqueKeysWithValues: customers.map { ($0.id, $0) })
                    self.posts = posts.map { submit in
                        if let consumer = userDict[post.userId] {
                            return PostWithUser(submit: submit, consumer: consumer)
                        } else {
                            return PostWithUser(submit: submit, consumer: MockData.mockUser)
                        }
                    }
                case .failure(let error):
                    print("Did not fetch consumer profiles: (error)")
                }
            }
        }
    }
    
    func deletePost(postId: String) {
        PostService.shared.deletePost(postId: postId) { lead to
            swap outcome {
            case .success:
                print("submit deleted")
            case .failure(let error):
                print("Did not delete submit: (error.localizedDescription)")
            }
        }
    }
}

import Firebase
import FirebaseFirestore
import FirebaseStorage
import SwiftUI

class PostService {
    static let shared = PostService()
    let db = Firestore.firestore()
    let postsRef = Firestore.firestore().assortment("posts")
    let usersRef = Firestore.firestore().assortment("customers")
    let storageRef = Storage.storage().reference()
    non-public var cachedPosts: [PostWithUser] = []
    
    func savePost(textual content: String, picture: UIImage?, videoURL: URL?, isPinned: Bool, parentId: String, groupId: String, completion: @escaping (End result<Void, Error>) -> Void) {
        guard let currentUser = Auth.auth().currentUser else {
            completion(.failure(NSError(area: "PostService", code: -1, userInfo: nil)))
            return
        }
        
        let uid = currentUser.uid
        let newPostRef = postsRef.doc()
        
        if let picture = picture {
            uploadImage(picture, postId: newPostRef.documentID) { lead to
                swap outcome {
                case .success(let imageUrl):
                    if let videoURL = videoURL {
                        self.uploadVideo(videoURL, postId: newPostRef.documentID) { videoResult in
                            swap videoResult {
                            case .success(let videoUrl):
                                self.createPost(textual content: textual content, imageUrl: imageUrl, videoUrl: videoUrl, isPinned: isPinned, parentId: parentId, postId: newPostRef.documentID, groupId: groupId, uid: uid, completion: completion)
                            case .failure(let error):
                                completion(.failure(error))
                            }
                        }
                    } else {
                        self.createPost(textual content: textual content, imageUrl: imageUrl, videoUrl: "", isPinned: isPinned, parentId: parentId, postId: newPostRef.documentID, groupId: groupId, uid: uid, completion: completion)
                    }
                case .failure(let error):
                    completion(.failure(error))
                }
            }
        } else if let videoURL = videoURL {
            uploadVideo(videoURL, postId: newPostRef.documentID) { lead to
                swap outcome {
                case .success(let videoUrl):
                    self.createPost(textual content: textual content, imageUrl: "", videoUrl: videoUrl, isPinned: isPinned, parentId: parentId, postId: newPostRef.documentID, groupId: groupId, uid: uid, completion: completion)
                case .failure(let error):
                    completion(.failure(error))
                }
            }
        } else {
            self.createPost(textual content: textual content, imageUrl: "", videoUrl: "", isPinned: isPinned, parentId: parentId, postId: newPostRef.documentID, groupId: groupId, uid: uid, completion: completion)
        }
    }
    
    non-public func uploadImage(_ picture: UIImage, postId: String, completion: @escaping (End result<String, Error>) -> Void) {
        guard let imageData = picture.jpegData(compressionQuality: 0.8) else {
            completion(.failure(NSError(area: "PostService", code: -1, userInfo: [NSLocalizedDescriptionKey: "Image conversion failed."])))
            return
        }
        
        let imageRef = storageRef.youngster("post_images/(postId).jpg")
        
        imageRef.putData(imageData, metadata: nil) { metadata, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            imageRef.downloadURL { url, error in
                if let error = error {
                    completion(.failure(error))
                } else if let imageUrl = url?.absoluteString {
                    completion(.success(imageUrl))
                } else {
                    completion(.failure(NSError(area: "PostService", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to get download URL."])))
                }
            }
        }
    }
    
    non-public func uploadVideo(_ videoURL: URL, postId: String, completion: @escaping (End result<String, Error>) -> Void) {
        let videoRef = storageRef.youngster("post_videos/(postId).mp4")
        
        print("Importing video to (videoRef.fullPath)")
        
        do {
            // Make sure the video file is accessible
            let videoData = attempt Knowledge(contentsOf: videoURL)
            
            // Add video utilizing information
            videoRef.putData(videoData, metadata: nil) { metadata, error in
                if let error = error {
                    print("Did not add video: (error.localizedDescription)")
                    completion(.failure(error))
                    return
                }
                
                videoRef.downloadURL { url, error in
                    if let error = error {
                        print("Did not get video URL: (error.localizedDescription)")
                        completion(.failure(error))
                    } else if let videoUrl = url?.absoluteString {
                        print("Video uploaded efficiently: (videoUrl)")
                        completion(.success(videoUrl))
                    } else {
                        print("Did not get video URL: Unknown error")
                        completion(.failure(NSError(area: "PostService", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to get download URL."])))
                    }
                }
            }
        } catch {
            print("Did not entry video file: (error.localizedDescription)")
            completion(.failure(error))
        }
    }

    non-public func createPost(textual content: String, imageUrl: String, videoUrl: String, isPinned: Bool, parentId: String, postId: String, groupId: String, uid: String, completion: @escaping (End result<Void, Error>) -> Void) {
        let postData: [String: Any] = [
            "userId": uid,
            "text": text,
            "imageUrl": imageUrl,
            "videoUrl": videoUrl,
            "parentId": parentId,
            "groupId": groupId,
            "isPinned": isPinned,
            "timestamp": FieldValue.serverTimestamp(),
            "views": 0
        ]
        
        postsRef.doc(postId).setData(postData) { error in
            if let error = error {
                completion(.failure(error))
            } else {
                completion(.success(()))
            }
        }
    }

    func incrementPostViewCount(postId: String) {
        let postRef = postsRef.doc(postId)
        postRef.updateData(["views": FirebaseFirestore.FieldValue.increment(Int64(1))]) { error in
            if let error = error {
                print("Error updating views: (error.localizedDescription)")
            } else {
                print("Views up to date efficiently!")
            }
        }
    }
    
    func fetchPosts(completion: @escaping (End result<[PostWithUser], Error>) -> Void) {
        if !cachedPosts.isEmpty {
            completion(.success(cachedPosts))
            return
        }
        postsRef.order(by: "timestamp", descending: true).getDocuments { snapshot, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let paperwork = snapshot?.paperwork else {
                completion(.success([]))
                return
            }
            
            let group = DispatchGroup()
            var postsWithUsers: [PostWithUser] = []
            
            for doc in paperwork {
                group.enter()
                let information = doc.information()
                guard let userId = information["userId"] as? String,
                      let parentId = information["parentId"] as? String,
                      let groupId = information["groupId"] as? String,
                      let textual content = information["text"] as? String,
                      let imageUrl = information["imageUrl"] as? String,
                      let videoUrl = information["videoUrl"] as? String,
                      let isPinned = information["isPinned"] as? Bool,
                      let timestamp = information["timestamp"] as? Timestamp,
                      let views = information["views"] as? Int else {
                    group.go away()
                    proceed
                }
                
                let submit = Submit(id: doc.documentID, userId: userId, parentId: parentId, groupId: groupId, textual content: textual content, imageUrl: imageUrl, videoUrl: videoUrl, timestamp: timestamp.dateValue(), isPinned: isPinned, likedBy: [], views: views)
                
                self.usersRef.doc(userId).getDocument { userDocument, error in
                    defer { group.go away() }
                    
                    if let userDocument = userDocument, let userData = userDocument.information() {
                        let consumer = Person(
                            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

                        )
                        postsWithUsers.append(PostWithUser(submit: submit, consumer: consumer))
                    } else {
                        print("Did not fetch consumer information for userId: (userId), error: (String(describing: error))")
                    }
                }
            }
            
            group.notify(queue: .primary) {
                self.cachedPosts = postsWithUsers
                completion(.success(postsWithUsers))
            }
        }
    }
    
    func refreshPosts(completion: @escaping (End result<[PostWithUser], Error>) -> Void) {
        cachedPosts = []
        fetchPosts { lead to
            print("posts refreshed")
        }
    }
    
    func deletePost(postId: String, completion: @escaping (End result<Void, Error>) -> Void) {
        let postRef = postsRef.doc(postId)
        
        postRef.getDocument { doc, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let doc = doc, doc.exists else {
                completion(.failure(NSError(area: "PostService", code: -1, userInfo: [NSLocalizedDescriptionKey: "Post not found."])))
                return
            }
            
            let information = doc.information()
            if information?["imageUrl"] is String {
                let imageRef = self.storageRef.youngster("post_images/(postId).jpg")
                imageRef.delete { error in
                    if let error = error {
                        print("Did not delete picture: (error.localizedDescription)")
                    }
                }
            }
            
            postRef.delete { error in
                if let error = error {
                    completion(.failure(error))
                } else {
                    self.cachedPosts.removeAll { $0.submit.id == postId }
                    completion(.success(()))
                }
            }
        }
    }
}

I have been experiencing this subject for hours now, can somebody please assist?



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments