M5L14 : The Challenge

The challenge is, essentially, to retrieve a piece of random text data from a website and display it, with an added link to change the data when prompted by the user.

Retrieving remote data is something that appeals to me, as I’ve done quite a lot of that in the past with other languages and so I know how useful it is. I thought that, as we’d done remote JSON parsing in previous lessons, this would be fairly straightforward, but it adds a new wrinkle into the mix:

let StringData = String(data: data, encoding: .utf8)

Compare this to when we previously fetched remote JSON data:

let urlString="(remote URL)"
let url = URL(string: urlString)
let modules = try decoder.decode([Module].self, from: data!)
let request = URLRequest(url: url!)
let session = URLSession.shared
let dataTask = session.dataTask(with: request) { (data, response, error) in
let decoder = JSONDecoder()
    let modules = try decoder.decode([Module].self, from: data!)
    self.modules += modules
}
dataTask.resume()

Or when we previously used local JSON data:

let jsonUrl = Bundle.main.url(forResource: "data", withExtension: "json")
let jsonData = try Data(contentsOf: jsonUrl!)
let jsonDecoder = JSONDecoder()
let modules = try jsonDecoder.decode([Module].self, from: jsonData)
self.modules = modules

And for regular local HTML data (a stylesheet):

let styleUrl = Bundle.main.url(forResource: "style", withExtension: "html")
let styleData = try Data(contentsOf: styleUrl!)
self.styleData = styleData

Smoothing off the code by looking at the solution for this challenge, this is how remote data (that isn’t JSON, so doesn’t need parsing), is retrieved (in a class, of course):

@Published var text = ""
    
    init() {
        getData()
    }
    
    func getData() {
        let urlString = "(remote URL)"
        if let url = URL(string: urlString) {
            URLSession.shared.dataTask(with: url) { (data, response, error) in
                if let error = error {
                    print(error.localizedDescription)
                    return
                }
                if let data = data {
                    if let stringData = String(data: data, encoding: .utf8) {
                        DispatchQueue.main.async {
                            self.text = stringData
                        }
                    }
                }
            }
            .resume()
        }
    }

I had gleaned most of from comparing the previous methods that we’ve been through in the lessons, but it still took me some time to understand how String(data: data, encoding: .utf8)is used with the rest of the code.

I had no idea where DispatchQueue.main.async {} in the solution came from, or what it does, but it turns out there’s an addendum video after the challenge which explains what it is and why we should use it.

The basic gist is that there are two threads in Swift. The ‘main’ thread that deals with the display, and the ‘background’ thread that does everything else. A ‘background’ thread should not interact directly with the ‘main’ thread because that could slow down the ‘main’ thread and produce a less than desirably user experience when the display is interrupted. So we use DispatchQueue.main.async {} whenever we need the ‘background’ thread to update the ‘main’ thread. This effectively places the request in a queue for the ‘main’ thread to deal with at its next available opportunity.

I’ll leave this here for future reference, as I’ve no doubt I’ll be needing it again.

It seems to me that the latter end of this module and the challenge have been quite erractic “bitty” affairs, what with having to deal with changes to Xcode, and things that weren’t covered in the lessons. Maybe that’s part of learning a new language that is constantly evolving, but it sure makes it more difficult to get things into logical order in your head.


Lesson 14 Challenge

On completing the challenge, I realised that even the simplest things need a lot of getting straight in my head.

This has a lot to do with doing things differently in other languages, and my head is so cemented on “how we did things in PHP”, that I crammed into my head during the last 6-8 months, that I’m having the toughest time getting off that path and onto the SwiftUI path.

I know I shall get there because there are more similarities than differences but, for now, having multiple stumbling blocks of things we haven’t covered before we get to the challenge for things we have covered is just proving too much for my ancient brain. But I have faith!

The final part of Module 5 of the iOS Foundations course from CodeWithChris is a Wrap-Up Challenge. With the way my head is buzzing trying to make sense of all the debugging of the last few lessons, I’m really not sure how I’m going to handle another challenge.

Neverthless, let’s do this