skip to Main Content

Im trying to create a small and simple app.

  • iOS
  • Reads single value from remote JSON file (ie a true/false)
  • Displays the value in a UI label on screen

This is the initial idea…but I eventually hope to read the value, and depending on whether true or false…perform some other functionality.

At this stage, just want to read and display it on screen.

Here is what I have so far and it works as far as printing to the log, but not to the screen/UILabel which is my goal.

import UIKit

struct DemoData: Codable {
    let title: String
    let description: String
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
 
        
        
        let urlString = "https://subdomain.domain.com/json/myData.json"
        self.loadJson(fromURLString: urlString) { (result) in
            switch result {
            case .success(let data):
                self.parse(jsonData: data)
            case .failure(let error):
                print(error)
            }
        }
        
        
        let labelRect = CGRect(x: 50, y: 100, width: 200, height: 100)
        let label = UILabel(frame: labelRect)
        label.text = "Description should be here"
        label.numberOfLines = 2
        view.addSubview(label)
        
        
        // Do any additional setup after loading the view.
    }
    
    private func loadJson(fromURLString urlString: String,
                          completion: @escaping (Result<Data, Error>) -> Void) {
        if let url = URL(string: urlString) {
            let urlSession = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
                if let error = error {
                    completion(.failure(error))
                }
                
                if let data = data {
                    completion(.success(data))
                }
            }
            
            urlSession.resume()
        }
    }

    private func parse(jsonData: Data) {
        do {
            let decodedData = try JSONDecoder().decode(DemoData.self,
                                                       from: jsonData)
            
            print("Title: ", decodedData.title)
            print("Description: ", decodedData.description)
            print("===================================")
        } catch {
            print("decode error")
        }
    }
}

Here is the JSON file that is hosted remotely…it will just say true or false, this is what Im using to get it working.

{
    "title": "Remote file",
    "description": "This is text from the remote JSON file"
}

Its not pretty, but Im hoping to solve small things as I move on with my idea….any help I would be extremely grateful.

Many thanks everyone 🙂

2

Answers


  1. Currently you’re creating the label within the scope of viewDidLoad(). The value from the JSON response won’t be available yet, since it is asynchronously fetched.

    If you make the label a class property instead and set its text to decodedData.title in the same place where you’re currently printing out the value, it should populate correctly.

    let label = UILabel()
    
    private func parse(jsonData: Data) {
        do {
            let decodedData = try JSONDecoder().decode(DemoData.self,
                                                       from: jsonData)
            
            DispatchQueue.main.async { [weak self] in
                self?.label.text = decodedData.title
            }
    
            print("Title: ", decodedData.title)
            print("Description: ", decodedData.description)
            print("===================================")
        } catch {
            print("decode error")
        }
    }
    

    P.S.: make sure you add [weak self] at the beginning of your loadJson(fromURLString: urlString) completion block in viewDidLoad() to avoid trying to access self after it’s been deallocated 🙂

    Login or Signup to reply.
  2. First of all declare the label lazily on the top level of the view controller to have a reference

    lazy var label : UILabel = {
        let labelRect = CGRect(x: 50, y: 100, width: 200, height: 100)
        let uiLabel = UILabel(frame: labelRect)
        uiLabel.text = "Description should be here"
        uiLabel.numberOfLines = 2
        return uiLabel 
    }()
    

    then assign the value after the line to print the description in parse

    ...
        print("===================================")
        DispatchQueue.main.async {
            self.label.text = decodedData.description
        }
    } catch { ...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search