scroll view does not update to new data

so I have two functions the first gets an array of structs and the second func gets another struct object and appends it to the first array. In my view I have a scroll view that displays all these elements in the array. When I run the code with the getAd function commented out (does not execute at all) the view displays the correct array of elements in the scroll view. but when I uncomment the getAd function the view does not display any elements at all. But I added a button to print the viewModel.new array, and when I click it, the correct array is printed out WITH the final element appended. Since the app works fine when the second function is commented out, it leads me to believe that the second func is causing the problem, but when I print the array with the button, the result looks just fine how I want it to look. Im not sure what the problem is, maybe the asynchronous nature of the functions.

view

import SwiftUI

struct FeedView: View {
    @StateObject var viewModel = FeedViewModel()

    var body: some View {
        mainInterFaceView
    }
}
extension FeedView{
    var mainInterFaceView: some View{
        VStack(){
            ZStack(){
                    ScrollView {
                        LazyVStack {
                            ForEach(viewModel.new) { tweet in
                               TweetRowView(tweet: tweet, hasDivider: true)
                            }
                        }
                    }
                }
            }
        }
    }
}

viewModel:

class FeedViewModel: ObservableObject{
    @Published var new = [Tweet]()
    var ads = [Tweet]()
    let service = TweetService()
    let userService = UserService()

    init(){
        fetchNew()
    }
    
    func fetchNew(){
        service.fetchNew { tweets in
            self.new = tweets

            for i in 0 ..< tweets.count {
                let uid = tweets[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.new[i].user = user
                }
            }
            self.getAd() //here
        }
    }
    func getAd() {
        service.fetchAd { ads in
            self.ads = ads

            for i in 0 ..< ads.count {
                let uid = ads[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.ads[i].user = user
                }
            }
            self.new.append(self.ads[0])
    }
}
Answered by ahmedzaidanzaidan in 745551022

Hello so I have two functions, the first gets tweets and the second gets ads and inserts them into the first array, for some reason calling the getAd function makes all the tweets.user var equal to nil. So when I run the app I briefly see all the tweets, then they disappear because the getAd function is called and their user values become nil. And after this only the ad is displayed. How can I fix this so that the user values do not become nill, I think this is an asynchronous issue and that's why I tried to do it inside the closer when i == count -1, but this did not work.

class FeedViewModel: ObservableObject{
    @Published var new = [Tweet]()
    var ads = [Tweet]()
    let service = TweetService()
    let userService = UserService()

    init(){
        fetchNew()
    }
    
    func fetchNew()  {
        service.fetchNew { tweets in
            self.new = tweets
            self.lastNew = tweets.last?.timestamp ?? Timestamp(seconds: 2, nanoseconds: 2)
            
            for i in 0 ..< tweets.count {
                let uid = tweets[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.new[i].user = user
                    if i == (tweets.count - 1){
                        self.new.sort { $0.promoted < $1.promoted }
                        self.getAd(myArray: tweets, direction: 1)
                    }
                }
            }
        }
    }
    func getAd(myArray: [Tweet], direction: Int) {
        var localArray = myArray
        service.fetchAd { ads in
            self.ads = ads
            self.lastAd = ads.last?.timestamp ?? Timestamp(seconds: 2, nanoseconds: 2)
            self.ads.sort { $0.plus ?? true && !($1.plus ?? false) }
            
            for i in 0 ..< ads.count {
                let uid = ads[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.ads[i].user = user
                    if i == (ads.count - 1){
                            let a = self.ads[0]
                            localArray.append(a)
                            self.new = localArray
                    }
                }
            }
        }
    }
Accepted Answer

Hello so I have two functions, the first gets tweets and the second gets ads and inserts them into the first array, for some reason calling the getAd function makes all the tweets.user var equal to nil. So when I run the app I briefly see all the tweets, then they disappear because the getAd function is called and their user values become nil. And after this only the ad is displayed. How can I fix this so that the user values do not become nill, I think this is an asynchronous issue and that's why I tried to do it inside the closer when i == count -1, but this did not work.

class FeedViewModel: ObservableObject{
    @Published var new = [Tweet]()
    var ads = [Tweet]()
    let service = TweetService()
    let userService = UserService()

    init(){
        fetchNew()
    }
    
    func fetchNew()  {
        service.fetchNew { tweets in
            self.new = tweets
            self.lastNew = tweets.last?.timestamp ?? Timestamp(seconds: 2, nanoseconds: 2)
            
            for i in 0 ..< tweets.count {
                let uid = tweets[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.new[i].user = user
                    if i == (tweets.count - 1){
                        self.new.sort { $0.promoted < $1.promoted }
                        self.getAd(myArray: tweets, direction: 1)
                    }
                }
            }
        }
    }
    func getAd(myArray: [Tweet], direction: Int) {
        var localArray = myArray
        service.fetchAd { ads in
            self.ads = ads
            self.lastAd = ads.last?.timestamp ?? Timestamp(seconds: 2, nanoseconds: 2)
            self.ads.sort { $0.plus ?? true && !($1.plus ?? false) }
            
            for i in 0 ..< ads.count {
                let uid = ads[i].uid
                self.userService.fetchUser(withUid: uid) { user in
                    self.ads[i].user = user
                    if i == (ads.count - 1){
                            let a = self.ads[0]
                            localArray.append(a)
                            self.new = localArray
                    }
                }
            }
        }
    }
scroll view does not update to new data
 
 
Q