Categories
Uncategorized

How to parse JSON with Swift 5

In this tutorial, we talk about a very important concept when it comes to working with APIs: Parsing JSON. We’ll talk about how to download JSON data from an URL and how to make use of it by encoding it. We learn all of this the easy way with using the Codable protocol!

What we want to achieve 🚀

Supposed we have an API that allows us to download images via their url’s and the usernames of the uploader, we want to create an app that displays that image with the according username. It should look similar to this:

The JSON data we use for this looks like this:

In this tutorial, we start with learning how to download the JSON data and how to parse it so we can extract the image URL’s and the usernames.

Creating the data model for our JSON data 🛠

Take a look at the JSON data above. It contains three entries (001, 002, and 003), where each has one imageURL and one uploaderName. To parse the JSON, we first need to define suitable data models for storing the parsed data later on.

Our data model we start with is the one we use for the entries’ content, the image data. We use a struct containing an imageURL and uploaderName property for this.

struct Image: Codable {
    let imageURL: String
    let uploaderName: String
}

Our second data model is for the entries itself. The only property of this model is a dictionary, where the key is the name of the entry (e.g. 001) and the value an instance of our just created Image model.

struct Entry: Codable {
    let images: [String: Image]
}

You see that we needed to create two different “model layers”, just as our JSON data has two “layers”.

Tip: Especially when it comes to more complex JSON data, you can use a tool such as quicktype, which automatically creates data models out of your JSON, ready for being used in your Swift project.

Downloading the JSON data ⬇️

Now we are ready to download our JSON data. I uploaded my sample JSON data to the web using this free tool. You can do this too if you want and then use the generated URL for retrieving the data. In real life you would use the API url from now on.

We start with creating a Swift URL object out of our URL.

if let url = URL(string: "http://www.json-generator.com/api/json/get/cfpeTpOFrC?indent=2") {
//
}

We can then retrieve the JSON data from the URL like this:

if let url = URL(string: "http://www.json-generator.com/api/json/get/cfpeTpOFrC?indent=2") {
   URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
//...
       }
   }.resume()
}

Parsing the JSON data 💡

To decode the JSON data we have to initialize a JSONDecoder.

if let url = URL(string: "http://www.json-generator.com/api/json/get/cfpeTpOFrC?indent=2") {
   URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
       }
   }.resume()
}

We can now parse the JSON by using the Decoder and our created data models. We do this inside a try-catch block to print out the error when something goes wrong with the parsing process.

if let url = URL(string: "http://www.json-generator.com/api/json/get/cfpeTpOFrC?indent=2") {
   URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(Entry.self, from: data)
        } catch {
print(error)
        }
       }
   }.resume()
}

At this point the parsedJSON property is assigned to an instance of our Entry class. This means that the parsedJSON contains a dictionary, where the values are instances of the Image class.

Therefore we can cycle through every Image instance of our Entry’s dictionary and grab the imageURL and uploaderName of each one.

if let url = URL(string: "http://www.json-generator.com/api/json/get/cfpeTpOFrC?indent=2") {
   URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(Entry.self, from: data)
for image in parsedJSON.images {
print(image.value.imageURL)
print(image.value.uploaderName)
            }
        } catch {
print(error)
        }
       }
   }.resume()
}

We could now use this data for downloading the images via the image URLs and displaying the according uploader user names. In the next tutorial (dropping in the very next days) we’ll see how to do this in SwiftUI. If you want to know how to download images in UIKit, take a look at this tutorial!

Conclusion 🎊

Great, we just learned how to retrieve and parse JSON data from the web by using the Codeable protocol and our own data models. You are now able to work with API’s that provide data via JSON.

If you want to see more, make sure you follow us on Instagram and subscribe to our newsletter to not miss any updates, tutorials and tips about SwiftUI and more!

Have any questions about this article? Write it in the comments below 👇

Categories
Uncategorized

How to use SwiftUI in a Playground

Xcode Playgrounds are a great way to test new ideas quickly and easily. You might have wondered if it is also possible to use SwiftUI views in a playground. And yes, it’s actually very straightforward 👇

Step 1: After you have created a playground, the first step is to import the necessary frameworks.

import UIKit
import PlaygroundSupport
import SwiftUI

Step 2: Next, you can create your SwiftUI view.

struct MyView: View {
    var body: some View {
        VStack {
            Text("Hello World!")
                .font(.title)
            Text("This a SwiftUI view")
        }
    }
}

Step 3: Before we can display this view, we need to convert it into an UIViewController. We do this by using an UIHostingController.

let viewController = UIHostingController(rootView: MyView())

Step 4: Finally, we use this view controller for the live view of our playground.

PlaygroundPage.current.liveView = viewController

If we run our playground now, we get our SwiftUI view displayed in a kind of preview simulator!

If you want to learn more about SwiftUI, make sure you follow us on Instagram and subscribe to our newsletter to not miss any updates, tutorials and tips!

Categories
Uncategorized

How to prevent the keyboard from hiding your SwiftUI view

To deliver a good user experience, you have to make sure that the user can see what he is typing. Therefore, it’s crucial to prevent the toggled keyboard from hiding your view’s content.


We can achieve this by offsetting the whole SwiftUI view by the height of the toggled keyboard. We could use a fixed value for this, but keep in mind that for example, the keyboard height of an iPhone 8 differs tremendously from the height of an iPad Pro. So how can we access the keyboard’s heigh and use it for offsetting our SwiftUI view? Well, here you go:

If you want to learn how to create a login screen like the one you see in the preview video, take a look at this tutorial or download the finished project.

Step 1: Create a new Swift file called KeyboardResponder and import the SwiftUI framework. Then create a class that adopts the ObservableObject protocol. Our KeyboardResponder needs to be observable so we can update the observing views when the keyboard got toggled.⠀

import Foundation
import SwiftUI

class KeyboardResponder: ObservableObject {

}

Step 2: For keeping track of the keyboard’s current height, we declare a @Published property and assign it to 0 by default. 0 represents that the keyboard is not opened. Whenever the keyboard shows up we will update the published property with the actual keyboard height which will cause the observing views to update themselves.⠀

class KeyboardResponder: ObservableObject {

    @Published var currentHeight: CGFloat = 0

}

Step 3: To achieve this, we can use the system’s built-in keyboardWillShowNotification and keyboardWillHideNotifaction. To handle these notifications, we need to initialise a NotificationCenter first.⠀

class KeyboardResponder: ObservableObject {
//...
    
var _center: NotificationCenter

    init(center: NotificationCenter = .default) {
        _center = center
    }
}

Step 4: Then we tell our notification center to listen to the system’s keyboardWillHide/Show notifications. Whenever the keyboards gets shown/hidden now, the Notification Center will execute the function targeted by the specific selector.⠀

init(center: NotificationCenter = .default) {
        _center = center
    //4. Tell the notification center to listen to the system keyboardWillShow and keyboardWillHide notification
        _center.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        _center.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

Step 5: Until now, we didn’t implement the functions called by the selectors. Let’s change this by adding these to our KeyboardResponder. Whenever the keyboard gets toggled now, our Notification Center notices and calls the corresponding function. Inside this function, we update the currentHeight property by referring to the keyboard size. As said this will cause all observing views to update themselves.

@objc func keyBoardWillShow(notification: Notification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            withAnimation {
               currentHeight = keyboardSize.height
            }
        }
    }
@objc func keyBoardWillHide(notification: Notification) {
        withAnimation {
           currentHeight = 0
        }
    }

Step 6: To observe the KeyboardResponder we have to initialise it inside our SwiftUI view as an @ObservedObject.

struct ContentView: View {
//...
    
@ObservedObject var keyboardResponder = KeyboardResponder()
var body: some View {
//...
    }
}

Step 7: Finally we tell our view to have the same offset as the keyboard is high by referring to the currentHeight variable of the observed KeyboardResponder.

var body: some View {
        NavigationView {
//...
        }
            .offset(y: -keyboardResponder.currentHeight*0.9)
    }

If you now run your app and open the keyboard, for example by tapping on a text field, the whole content moves up so we’re able to read what we’re writing.

That’s it! I hope you enjoyed this brief SwiftUI tutorial! 🍀

You can download the full source code here.

By the way, did you already download our FREE SwiftUI Basics eBook? Make sure you click the link in the bio to check it out 🚀