0
votes

I've a proble with Array using ObservableObject in my view.I've an empty array. I call a function at page onAppear. When data return the view not update with the new data in array:

class NewsState: ObservableObject {

    private let base: String = "api"
    let objectWillChange = ObservableObjectPublisher()

    @Published var wagsList: Array<UserSlider> = [] {
        willSet {
            objectWillChange.send()
        }
    }

    func getList() {
        let url = NSURL(string: "\(base)/UserApi/getList")
        var mutableURLRequest = URLRequest(url: url! as URL)
        mutableURLRequest.httpMethod = "GET"
        mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
        AF.request(mutableURLRequest).responseData { response in
            guard let data = response.data else { return }
            let resp = try! JSONDecoder().decode(Array<UserSlider>.self, from: data)
            for i in resp {
                let userSlider = UserSlider(id: i.id, uid: i.uid, image: i.image)
                self.wagsList.append(userSlider)
            }
        }
    }
}

in my view I've this:

HStack {
                                ScrollView(.horizontal, showsIndicators: false) {
                                    HStack(spacing: 20) {
                                        if(self.newsState.wagsList.count != 0) {
                                            ForEach(self.newsState.wagsList, id: \.self) { wags in
                                                VStack {
                                                    HStack {
                                                        URLImage(URL(string: "\(wags.image)")!, expireAfter: Date(timeIntervalSinceNow: 10)) { proxy in
                                                            proxy.image
                                                                .renderingMode(.original)
                                                                .resizable()
                                                                .aspectRatio(contentMode: .fill)
                                                                .frame(width: 60, height: 60)
                                                                .clipShape(Circle())
                                                                .overlay(
                                                                    RoundedRectangle(cornerRadius: 30)
                                                                        .stroke(Color.white, lineWidth: 2)
                                                                )
                                                                .contentShape(Circle())
                                                        }.frame(width: 62, height: 62)
                                                    }
                                                    HStack {
                                                        Text("10K")
                                                            .foregroundColor(Color.white)
                                                            .font(Font.custom("Metropolis-Bold", size: 15))
                                                    }
                                                    HStack {
                                                        Text("followers")
                                                            .foregroundColor(Color.white)
                                                            .font(Font.custom("Metropolis-Normal", size: 15))
                                                    }
                                                }
                                            }
                                        } else {
                                            //loader
                                        }
                                    }.onAppear(perform: initPage)
                               }
                            }

Where i'm wrong? I've see that the problem is caused by ScrollView

2
Have you for e.g. printed out the array before and after the on appear? This would help to determine where the error might lay. It can be either in the getList or also in your View. - Simon
Why do you even use ObservableObjectPublisher? Published should already do that. Also, as you are using willSet here, just know that there's a bug related with those functions not calling on Xcode 11.4 and 11.4.1. See here: stackoverflow.com/questions/60907882/… - Cuneyt

2 Answers

0
votes

Try this one

class NewsState: ObservableObject {

    private let base: String = "api"

    @Published var wagsList: Array<UserSlider> = []

    func getList() {
        let url = NSURL(string: "\(base)/UserApi/getList")
        var mutableURLRequest = URLRequest(url: url! as URL)
        mutableURLRequest.httpMethod = "GET"
        mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
        AF.request(mutableURLRequest).responseData { response in
            guard let data = response.data else { return }
            let resp = try! JSONDecoder().decode(Array<UserSlider>.self, from: data)

            let results = resp.map { UserSlider(id: $0.id, uid: $0.uid, image: $0.image) }
            DispatchQueue.main.async {
                self.wagsList = results
            }
        }
    }
}
0
votes

As it is not clear to me where the error might lay. It could be either in getList or in your View.

This is an easy example of how it works with a Published and ObserverdObject: Note: your getList function is not in this solution as the error could be with your API, JSON ect.

import SwiftUI

struct ContentView: View {

    @ObservedObject var state = NewsState()

    var body: some View {
        Group { //needed for the IF Statement below
            if state.stringList.count > 0 {
                ForEach(self.state.stringList, id: \.self){ s in
                    Text(String(s))
                }
            }
        }.onTapGesture {
            self.state.getNewList()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


class NewsState: ObservableObject {

    @Published var stringList: Array<String> = []

    init() {
        self.getList()
    }

    func getList() {
        self.stringList.append("New")
    }

    func getNewList() {
        self.stringList = []
        self.stringList.append("New new")
    }
}