AboutContact

SwiftUI: how to download and parse json data and display in a list using the swift UI PreviewProvider

In this new SwiftUI tutorial you will learn with a simple example how to asynchronously download json data from an url, parse the data using the new Swift decodable struct utility, how to use the SwiftUI to define a custom view, display the data in a swiftui list. You will also learn how to navigate to a new view using SwiftUI by passing the data to the new view.

Getting started: create the SwiftUI project

Let's start by creating a new iOS app, using the SwiftUI interface builder instead of the usually storyboard.

swiftui interface builder: let's create a new swift project

Here how to SwiftUI interface builder project looks like. Xcode automatically creates the first view, subclass of the new PreviewProvider protocol. Every struct that defines the PreviewProvider protocol is allowed to be previewed on the right side.swift_ui_project

On the right side, as you can see, there is the real time results of your app. Every time you do changes on the code, the interface is updated to let you see the final result. Of course at any time you can also run the iOS simulator or run your app on a real device to see and better try your app.

Download, parse and display JSON data in a SwiftUI list

In this tutorial we'll use the list of country json data. This is a simple structure, defined by a list of object.

[]List - {} Object - country, code

In the JSON data structure, you can recognize a list with the [...] brackets, an object with the {...} brackets.

So, every single row has two strings that contain the country and the code. Here you can find the data.

Let's start by defining the CountryStruct Decodable struct. This struct should contains the country and code strings of our data.

struct Country: Decodable {
    var country: String
    var code:String
}

Let's modify now the ContentView.swift file. The view should display a list.

import SwiftUI


struct ContentView: View {
    @State private var countryData = [Country]()
    
    var body: some View {
        
        List(countryData, id: \.code) { item in

                HStack() {
                    Text(item.country)
                        .font(.headline)
                    Text(item.code)
                        .font(.footnote)
                }
	}

    }
    
    
}

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

As you can see, we'll use the SwiftUI list functionality. Each row is defined by an HStack, namely an horizontal stack, with two text views, that will display the country and code respectively.

Download and parse the JSON data

We need now to download and parse the data, let's add the onAppear list method, that is called as soon as the list is visible. The onAppear method will then call the function that will download the json data, parse the json data in swift object using the previously defined struct.

import SwiftUI


struct ContentView: View {
    @State private var countryData = [Country]()
    
    var body: some View {
        
        NavigationView{List(countryData, id: \.code) { item in
            NavigationLink(destination: CountryDetail(country: item)) {
                
                HStack() {
                    Text(item.country)
                        .font(.headline)
                    Text(item.code)
                        .font(.footnote)
                }
                
            }.navigationBarTitle("Country List")
            
        }.onAppear(perform: loadData)}
        
    }
    
    
}

extension ContentView
{
    func loadData() {
        
        guard let url = URL(string: "https://kaleidosblog.s3-eu-west-1.amazonaws.com/json/tutorial.json") else {
            return
        }
        
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { data, response, error in
            
            if let data = data {
                if let response_obj = try? JSONDecoder().decode([Country].self, from: data) {
                    
                    DispatchQueue.main.async {
                        self.countryData = response_obj
                    }
                }
            }
            
        }.resume()
    }
}


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

The NavigationView and NavigationLink are used to let the user navigate on the detail view as soon as a row is tapped. The tapped country data is passed to the next view.

Define the detail view

Let's define now the detail view that will display the selected country details. As an input the view requires the tapped country detaill

struct CountryDetail: View {
    var country: Country
    
    var body: some View {
        
        VStack(alignment: .leading, spacing: 10) {
            Text(country.country)
                .font(.headline)
            Text(country.code)
                .font(.footnote)
        }
    }
}

The view is defined with a vertical stack, namely VStack, with two Text, that display again the country and code. The leading alignment is used to align the sub views on the leading side, you can also use the center alignment method.

Here you can download the example:

Download

Leave a comment








Comments


- 20 June 2020 at 04:46
Hello Great Blog. When I your app, I note that once I dismiss the app on my phone, then disconnect from the internet and re-open your app, the data is still there persisted in the app. I don't see the you are using CoreData or any kind of framework to persist the data, so wondering what you do, or what it is that allows for the data to be persisted? Sorry if the question is simple, I am still very new to this. Thank you
foo bared - 05 July 2020 at 01:28
foo bar? bared baz, qux quux! also qux as foo, when baz as bar. do you understand me?





AboutContactPrivacy