The request to help with alamofire (two days I cannot find and understand a mistake); on a task I need to obtain data of JSON through api and automatically "to spread out" them in

var articles = [Articles]()

These value (JSON) come and printed, but because of the wrong method / structure I cannot automatically spread out them.

let api_url = "https://newsapi.org/v2/everything?q=bitcoin&from=2019-03-13&sortBy=publishedAt&apiKey=xxx"

let formatter = "https://jsonformatter.curiousconcept.com/"

And

struct Articles: Decodable {

    var author: String?
    var content: String?
    var description: String?
    var publishedAt: String?
    var title: String?
    var url: String?
    var urlToImage: String?

    init(dict: [String: Any]) {

        let author = dict["author"] as? String ?? ""
        // some let's...
        let urlToImage = dict["urlToImage"] as? String ?? ""

        self.author = author
        // some self's...
        self.publishedAt = publishedAt
    }

    static func getArray(from arrayOfItems: Any) -> [Articles]? {
        guard let arrayOfItems = arrayOfItems as? Array<[String: Any]> 
        else { print("ERROR at ArticleModel -> Articles"); return nil }

        return arrayOfItems.compactMap { Articles(dict: $0) }
    }
}

//Download Data

func fetchDataWithAlamofire() {

    guard let url = URL(string: api_url) else { return }

    request(url).validate().responseJSON { (dataResponse) in

        switch dataResponse.result {
        case .success(let value):
            print(value)

            if let response = Articles.getArray(from: value) {
                self.articles = response
            }

            DispatchQueue.main.async {
                self.tableView.reloadData()
            }

        case .failure(let error):
            print(error)
        }
    }
}

Data of JSON which I obtained have to automatically (through a method) to spread out in the array and to be displayed in a simulator cell (I already made cells, a problem in Array/Dict/Struct)

1 Answers

1
vadian On

First of all why does your struct conform to Decodable although you don't use JSONDecoder at all?

You are making a common mistake, you are ignoring the root object. You need two structs and please name Article in singular form.

struct Root : Decodable {
    let status : String
    let totalResults : Int?
    let message : String? // message is used in case of an error
    let articles : [Article]?
}

struct Article : Decodable {

    let author : String?
    let content : String?
    let description : String
    let publishedAt : Date
    let title : String
    let url : URL
    let urlToImage : URL?
}

The initializer and the static func in Article is not needed.

In fetchDataWithAlamofire() use responseData rather than responseJSON and decode the JSON with JSONDecoder.
url and urlToImage can be decoded directly to URL and publishedAt can be decoded to Date

func fetchDataWithAlamofire() {

    guard let url = URL(string: api_url) else { return }

    request(url).validate().responseData { dataResponse in

        switch dataResponse.result {
        case .success(let data):
            do {
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .iso8601
                let result = try decoder.decode(Root.self, from: data)
                self.articles = result.articles

                DispatchQueue.main.async {
                   self.tableView.reloadData()
                }
            } catch {
                print(error)
            }

        case .failure(let error):
            print(error)
        }
    }
}