Swiftui JSON Won't Print Title in Scrollview Hstack (But Will in List)

SwiftUI JSON won't print title in ScrollView HStack (but will in List)

Please clean and build the project. The code seems to work fine.
I've created a new project and simply copied & pasted the above code that you've written and it is working correctly.

EDITED -
To show the list horizontally, please use below code:

var body: some View {
NavigationView {
if posts.isEmpty {
Text("Loading")
} else {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .center, spacing: 10) {
ForEach(posts) { post in
return Text(post.title)
}
}
}.frame(height: 200)
}
}.onAppear {
Api().getPosts { (posts) in
self.posts = posts
}
}.navigationBarTitle(Text("Home"))
}

Swift UI fetching JSON

The top level of your JSON has a parameter programs which in turn contains an array. You should update your code like this

import SwiftUI

// Add this top level struct to
// decode properly
struct Post: Codable {
var programs: [Program]
}

struct Program: Codable, Identifiable {
let id = UUID()
var title : String
var icon : String
}

class Api {
// Update this to return an array of Program
func getPosts(completion: @escaping ([Program]) -> ()) {
guard let url = URL(string: "https://api.drn1.com.au/api-access/programs/DRN1") else { return }

URLSession.shared.dataTask(with: url) { (data, _, _) in
// Based on the updated structs, you would no
// longer be decoding an array
let post = try! JSONDecoder().decode(Post.self, from: data['programs']!)
DispatchQueue.main.async{
// The array is stored under programs now
completion(post.programs)
}

}
.resume()
}
}

onAppear not displaying Interface Elements

Just to clarify the difference between init and onAppear() (accoding to comments)

Let's imagine you have a TabView with 2 views. First view is the view you created and provided code for, the second view could be a profile view. onAppear() function will be called each time the user switch between these two TabViews while init() function will only run once in this particular use case.

Next, it is important to note that URLSession is running on background thread. You can only update the Views from the MainThread which means, you should encapsulate the result into:

DispatchQueue.main.async {
self.results = decodedResponse.results
}

But the acutal answer to your Question

I just faced the same issue few days ago. ScrollView has some bug/feature at this moment, which means, if you try to ScrollView + ForEach an empty array that is going to be updated later it will not show up. If you give a hardcoded Article as your first item, and update the rest later, it will work. Atleast for me worked under swift5 xcode 11.3.1 on iOS 13.3.1. However I use ObservableObject to handle datas in a class and ObservedObject to take advantage of @Published modifier. Like this

class Result : ObservableObject{
@Published var results = [Article]()
}

And Write this to your swiftUI code:

@ObservedObject private var data = Result()

Your swiftui init function should contain an add function like so to bypass ScrollView bug/feature:

init() {
self.data.results.append(....)
self.callYourRestAPIHere(URL:"whateverhere", result: data)
}

Hope I did not miss anything, but I am ready to improve my Answer if I did.

Obj-C function not being called in SwiftUI

After further inspection I had noticed a plist missing in my project files. This plist is a placeholder for apps to install. Upon creating it my issue has been resolved. My apologies for making people waste time with trying to help me.



Related Topics



Leave a reply



Submit