how to print track data (swift) - ios

So I have the following code printing out the following
[DRN1.Data(track: DRN1.Trackinfo(title: "Charly\'s Ballad (Original Mix)", artist: "Castle Queenside", imageurl: "covers.drn1.com.au/az_B1017197_Disc 1 Traxsource Nu Disco & Indie Dance_Castle Queenside.jpg"))]
However when I go to write
print(nowplaying.data.track.title)
I get errors and it won't even attempt to load the swift app
struct Nowplayng: Decodable{
let data: [Data]
}
struct Data: Decodable{
let track: Trackinfo
}
struct Trackinfo: Decodable {
let title: String
let artist: String
let imageurl: String
}
works
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let jsonURLString = "https://api.drn1.com.au/station/playing"
guard let feedurl = URL(string: jsonURLString) else { return }
URLSession.shared.dataTask(with: feedurl) { (data,response,err)
in
guard let data = data else { return }
do{
let nowplaying = try JSONDecoder().decode(Nowplayng.self, from: data)
print(nowplaying.data)
}catch let jsonErr{
print("error json ", jsonErr)
}
// let dataAsString = String(data:data, encoding: .utf8)
// print(dataAsString)
}.resume()
}
does not work
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let jsonURLString = "https://api.drn1.com.au/station/playing"
guard let feedurl = URL(string: jsonURLString) else { return }
URLSession.shared.dataTask(with: feedurl) { (data,response,err)
in
guard let data = data else { return }
do{
let nowplaying = try JSONDecoder().decode(Nowplayng.self, from: data)
print(nowplaying.data.track.title)
}catch let jsonErr{
print("error json ", jsonErr)
}
// let dataAsString = String(data:data, encoding: .utf8)
// print(dataAsString)
}.resume()
}

data is an array you need to loop over it
nowplaying.data.forEach {
print($0.track.title)
}
If you care about the first item do
if let item = nowplaying.data.first {
print(item.track.title)
}

Related

Why am not able to access my model class in Swift Project?

How to access my Model from ViewController and use the Model data to load in table view????
Source Code Link
My ViewController looks like this
import UIKit
class ViewController: UIViewController {
var cclm: CountryCodeListModel?
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(hello), userInfo: nil, repeats: true)
readLocalJSONFile(forName: "countryList")
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
}
#objc func hello()
{
print(cclm?.data?[0].flag)
}
}
and my model class look like this
struct CountryCodeList : Decodable {
var alpha2Code: String?
var alpha3Code: String?
var flag : String?
var name : String?
var code : String?
}
public struct CountryCodeListModel : Decodable {
var data : [CountryCodeList]?
}
var cclm: CountryCodeListModel?
//Method to load json
func readLocalJSONFile(forName name: String) {
do {
if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
let fileUrl = URL(fileURLWithPath: filePath)
let data = try Data(contentsOf: fileUrl)
if let countryCodeObject = parse(jsonData: data) {
cclm = countryCodeObject
print(cclm?.data?[1].alpha2Code ?? "") //Printing Correct Value
}
}
} catch {
print("error: \(error)")
}
}
func parse(jsonData: Data) -> CountryCodeListModel?{
var dataArray : [Dictionary<String,Any>] = [[:]]
var country = Dictionary<String,Any>()
var modelData = Dictionary<String,Any>()
do {
// make sure this JSON is in the format we expect
if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? Dictionary<String,Any> {
dataArray.removeAll()
for item in json["data"] as! [Dictionary<String, Any>] {
country = item
let url = URL(string: country["flag"] as? String ?? "")
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
let image = UIImage(data: data!)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = url?.lastPathComponent // name of the image to be saved
let fileURL = documentsDirectory.appendingPathComponent(fileName ?? "")
if let data = image?.jpegData(compressionQuality: 1.0){
do {
try data.write(to: fileURL)
country["flag"] = fileURL.absoluteString
//print("file saved")
//urlAsString = fileURL.absoluteString
} catch {
print("error saving file:", error)
}
}
dataArray.append(country)
country.removeAll()
}
modelData["data"] = dataArray
//print(modelData)
let jsonData1 = try JSONSerialization.data(withJSONObject: modelData, options: [])
do {
let decodedData = try JSONDecoder().decode(CountryCodeListModel.self, from: jsonData1)
return decodedData
} catch {
print("error: \(error)")
}
}
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
return nil
}
Problem statement:
Iam reading local json and take the url value of flag key and download corresponding images to local. Once i download then am taking the localpath and update in the dictionary and then create JSON object and update my model class.
Now, am trying to access my model class from ViewController like below
print(CountryCodeListModel?.data?[0].name) //check screenshot for error
print(cclm?.data?[0].flag) // this prints nil always
Please check the error screenshots attached2
My JSON look like this
{
"meta":{
"success":true,
"message":"Successfully retrieved country details",
"code":"200"
},
"data":[
{
"alpha2Code":"AF",
"alpha3Code":"AFG",
"flag":"https://raw.githubusercontent.com/DevTides/countries/master/afg.png",
"name":"Afghanistan",
"code":"+93"
},
{
"alpha2Code":"AX",
"alpha3Code":"ALA",
"flag":"https://raw.githubusercontent.com/DevTides/countries/master/ala.png",
"name":"Aland Islands",
"code":"+358"
},
{
"alpha2Code":"AL",
"alpha3Code":"ALB",
"flag":"https://raw.githubusercontent.com/DevTides/countries/master/alb.png",
"name":"Albania",
"code":"+355"
},
{
"alpha2Code":"DZ",
"alpha3Code":"DZA",
"flag":"https://raw.githubusercontent.com/DevTides/countries/master/dza.png",
"name":"Algeria",
"code":"+213"
},
{
"alpha2Code":"AS",
"alpha3Code":"ASM",
"flag":"https://raw.githubusercontent.com/DevTides/countries/master/asm.png",
"name":"American Samoa",
"code":"+1684"
}
]
}
You are trying to decode something that doesn't exist.
print(CountryCodeListModel?.data?[0].name) //check screenshot for error
print(cclm?.data?[0].flag) // this prints nil always
The above code states that you want:
the name of
the variable data at position 0 of
the struct CountryCodeListModel.
What you want to do is:
the name of
the variable at position 0 of
an INSTANCE of the struct CountryCodeListModel.
For example...
func readLocalJSONFile(forName name: String) {
do {
if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
let fileUrl = URL(fileURLWithPath: filePath)
let data = try Data(contentsOf: fileUrl)
if let countryCodeObject = parse(jsonData: data) {
cclm = countryCodeObject
print(cclm?.data?[1].alpha2Code ?? "") //Printing Correct Value
print(cclm?.data?[0].flag ?? "")
print(countryCodeObject?.data[0].flag ?? "") // Same as the line above
}
}
} catch {
print("error: \(error)")
}
}
Unless you are trying to use a static variable (at which you would use CountryCodeListModel.data), you need to make sure you are actually using an instance of the structure or an object of a class to reference your properties.
CAVEAT
CountryCodeListModel is a structure. CountryCodeListModel() is an instance of the structure CountryCodeListModel. Since you can have multiple instances of a structure, you need to reference a specific structure when accessing data. Thus, CountryCodeListModel.data will not work and it needs to be CountryCodeListModel().data. In this case, you have cclm.data.

Nothing appearing the console when Decoding JSON in Swift

I'm trying to play around with a COVID dataset from Github (link in code below) but when I run the code nothing appears in the console. There are no errors appearing.
Can anyone advise on whats wrong here? Thanks in advance!
struct country: Decodable {
var location: String
var new_cases: Double
var people_fully_vaccinated: Double
}
func getJSON(){
guard let url = URL(string: "https://raw.githubusercontent.com/owid/covid-19-data/68c39808d445fe90b1fe3d57b93ad9be20f796d2/public/data/latest/owid-covid-latest.json") else{
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request){ (data, response, error) in
if let error = error{
print(error.localizedDescription)
return
}
guard let data = data else{
return
}
let decoder = JSONDecoder()
guard let decodedData = try? decoder.decode([country].self, from: data) else{
return
}
let countries = decodedData
for country in countries{
print (country.location)
}
}.resume()
}
getJSON()
You need
struct Root: Decodable {
var location: String
var new_cases: Double? // make it optional as it has some objects with nil
var people_fully_vaccinated: Double? // make it optional as it has some objects with nil
}
With
do {
let res = try decoder.decode([String:Root].self, from: data)
let locations = Array(res.values).map { $0.location }
print(locations)
}
catch {
print(error)
}

Json data not showing on tableView swift 5

I fetched the data and it is showing when printing but when i try to display it on tableview.Nothing is coming
Am i placing tableview.reloadData in wrong place ?
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
tableView.reloadData()
}
func fetchData()
{
if let url = URL(string: urlConstant) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, res, err) in
if err == nil
{
let decoder = JSONDecoder()
if let safeData = data
{
do{
let results = try decoder.decode(Results.self, from: safeData)
guard let array = results.Result as? [Products] else {return }
for product in array
{
self.productArray.append(product)
}
} catch {
print(error)
}
}
}
}
task.resume()
}
self.tableView.reloadData()
}
If you are getting correct response(check it once) from the server then next thing you need to reload tableView after getting the response from the server and populating the array.
func fetchData() {
if let url = URL(string: urlConstant) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, res, err) in
if err == nil
{
let decoder = JSONDecoder()
if let safeData = data
{
do{
let results = try decoder.decode(Results.self, from: safeData)
guard let array = results.Result as? [Products] else {return }
for product in array {
self.productArray.append(product)
}
// Reload table view here
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}
}
}
task.resume()
}
}
Alternative, you can add completion handled in fetchData method.

Why JsonDecoder Giving Error while trying to parse postman Url but working on other urls?

Both The Url contains Dictionary In Json Format.
import UIKit
import Foundation
struct Course : Decodable{
let foo1: String?
let foo2: String?
let fullName : String?
let numFound : Int?
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// let jsonUrl = "https://api.plos.org/search?q=title:DNA" //Working On this Url
let jsonUrl = "https://postman-echo.com/get?foo1=bar1&foo2=bar2"//Not Working On this Url
guard let url = URL(string: jsonUrl) else { return}
URLSession.shared.dataTask(with: url) {(data,response,err) in
guard let data = data
else {return}
do
{
let course = try JSONDecoder().decode([String: Course].self , from: data)
course.forEach { print("\($0.key): \($0.value)")}
}
catch let jerr
{
print(jerr)
}
}.resume()
}
}
This Is the Error If I am Using Postman Url
Paste the Postman URL into a browser and look at the JSON.
It doesn't work because there are other values than Course for other keys so decoding a [String:Course] dictionary fails.
You have to add an umbrella struct for the root object
struct Root : Decodable {
let args : Course
}
struct Course : Decodable {
let foo1: String?
let foo2: String?
let fullName : String?
let numFound : Int?
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// let jsonUrl = "https://api.plos.org/search?q=title:DNA" //Working On this Url
let jsonUrl = "https://postman-echo.com/get?foo1=bar1&foo2=bar2"//Not Working On this Url
guard let url = URL(string: jsonUrl) else { return}
URLSession.shared.dataTask(with: url) {(data,response,err) in
guard let data = data else {return}
do {
let result = try JSONDecoder().decode(Root.self , from: data)
print(result.args.foo1, result.args.foo2)
} catch {
print(error)
}
}.resume()
}
}

kingfisher not showing image

So I am using kingfisher as people have suggested its the way to go with remote images.
However I have a func that is meant to load now playing info
func nowplaying(){
let jsonURLString = "https://api.drn1.com.au/station/playing"
guard let feedurl = URL(string: jsonURLString) else { return }
URLSession.shared.dataTask(with: feedurl) { (data,response,err)
in
guard let data = data else { return }
do{
let nowplaying = try JSONDecoder().decode(Nowplayng.self, from: data)
nowplaying.data.forEach {
self.artist.text = $0.track.artist
self.song.text = $0.track.title
//self.artist.textAlignment = .center
//self.song.textAlignment = .center
print($0.track.title)
if let strUrl = nowplaying.data.first?.track.imageurl {
self.imageurl.kf.setImage(with: URL(string: strUrl), placeholder: nil)
}
//self.imageurl.setImage(with: $0.track.imageurl)
}
}catch let jsonErr{
print("error json ", jsonErr)
}
}.resume()
}
but while the song title and artist shows the image does not.
Actually url contains spaces that need to be percentage encoding.
if var strUrl = nowplaying.data.first?.track.imageurl {
strUrl = strUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
self.imageurl.kf.setImage(with: URL(string: strUrl), placeholder: nil)
}

Resources