Basic API into app to variables

Hi All -

I'm a new developer and have been having the hardest time attempting to get an API into my app. I created a blank app (pasted in) to essentially isolate all other possible things that could be affecting this, and am attempting to set each value in this test API I made to a variable in my app. I've spent hours watching YouTube videos and reading forums on here as well as on Reddit and nothing seems to help.

I was hoping someone who understood this better than I do would be able to explain to me how this should work.

Here's the very basic test app...

//Here's just my test app...

import swiftUI
import Foundation

// 
//
// The API is a URL which contains the following values.
//
// [{"value1":"12","value2":"15","value3":"19"}]
//
//This isn't going to be the final API I'm using, I just needed something easy to test with.

//I would like to assign the values from each of the values in the API to the variables below. This is the stage in the process where I seem to fall flat :(

var var1 = // First Value from API
var var2 = // Second Value from API
var var3 = // Third Value from API


struct ContentView: View {
     var body: some View {
          VStack{
               Text(var1)
               Text(var2)
               Text(var3)
          }
     }
}

struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
          ContentView()
     }
}

Any help would be appreciated - I'm 100% lost. I just started learning Swift and SwiftUI this fall and never had to deal with APIs before now. I'm used to using them in GoogleAppsScript and JS but I, for some reason, can't figure out how to use them on Swift.

Thank you to anyone who responds. Stay safe and healthy!

-James

This is more of a promotion (spam) for the sheetsu.co m site - ignore and mark as spam.

I, in no way intended to promote that website and am sorry if I gave off the wrong impression. Your point is completely valid, and I was unaware of it. Sorry for the confusion. I removed the URL to the API and replaced it with the contents of the API instead.

Is the point about json decoding ?

Then you could do something like:

let jsonString =  "{\"value1\":\"12\", \"value2\":\"15\", \"value3\":\"19\"}"    // Created for test purpose

var var1 = ""// First Value from API
var var2 = ""// Second Value from API
var var3 = ""// Third Value from API

struct AllVar: Codable {
    public var value1: String
    public var value2: String
    public var value3: String
}

func decode() -> AllVar? {
    
    var myVar : AllVar?
    let data = jsonString.data(using: .utf8, allowLossyConversion: false)  // Use directly the data you get from url
    
    let jsonDecoder = JSONDecoder()
    do {
        myVar = try jsonDecoder.decode(AllVar.self, from: data!)
        var1 = myVar?.value1 ?? ""
        var2 = myVar?.value2 ?? ""
        var3 = myVar?.value3 ?? ""
        return myVar
    } catch {
        print("Decode error", jsonString)
    }
    return nil
}


struct ContentView: View {
    
     var myVar = decode()
    
     var body: some View {
          VStack{
               Text(var1)
               Text(var2)
               Text(var3)
          }
     }
}

Or a bit cleaner:

let jsonString =  "{\"value1\":\"12\", \"value2\":\"15\", \"value3\":\"19\"}"    // Created for test purpose

struct AllVar: Codable {
    public var value1: String
    public var value2: String
    public var value3: String
}

func decode() -> AllVar? {
    
    var myVar : AllVar?
    
    let data = jsonString.data(using: .utf8, allowLossyConversion: false) // Use directly the data you get from url
    
    let jsonDecoder = JSONDecoder()
    do {
        myVar = try jsonDecoder.decode(AllVar.self, from: data!)
        return myVar
    } catch {
        print("Decode error", jsonString)
    }
    return nil
}


struct ContentView16: View {
    
     var myVar = decode()
    
     var body: some View {
          VStack{
               Text(myVar?.value1 ?? "")
               Text(myVar?.value2 ?? "")
               Text(myVar?.value3 ?? "")
          }
     }
}

In both cases, you get:

If you read from an url, code would like this:

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
           // some code
        }
        
        urlSession.resume()
    }
}

data contains what you are looking for.

Get more details here:

h t t p s : / / programmingwithswift.com/parse-json-from-file-and-url-with-swift/

And don't forget to close the thread on the correct answer.

I don't get your exact context, so some guessing.

I assume you have the url for the web site…

Hope that works as is, tell otherwise.

func decode() -> AllVar? {
    
    var myVar : AllVar?
    var data : Data?

    // SKIP THIS let data = jsonString.data(using: .utf8, allowLossyConversion: false) // Use directly the data you get from url
    
    if let url = URL(string: urlString) {  // urlString is the url
        let urlSession = URLSession(configuration: .default).dataTask(with: url) { (readData, response, error) in
           myData = readData
        }
        
        urlSession.resume()
    }


    let jsonDecoder = JSONDecoder()
    do {
        myVar = try jsonDecoder.decode(AllVar.self, from: data!)
        return myVar
    } catch {
        print("Decode error", jsonString)
    }
    return nil
}

.

Also, search in Xcode doc for Fetching Website Data into Memory for detailed examples.

Had to make this an answer since comments don't seem to like my Code snippets :(

Got a number of errors :(.

Thank you so much for helping me with this, once again. This is so helpful - I don't know what I would've done.

//Here are the errors I received..
//
//Example of how I formatted this...
// Line xx: {code that triggered error} → Error Message
//
//
//Line 26: {myData = readData} → Couldn't find myData in Scope
//Line 38: {print("Decode error", jsonString} → Cannot find 'jsonString' in scope
//Line 46: {Text(myVar?.value1 ?? "")} → Cannot find 'myVar' in scope

//Here's the code...
import SwiftUI
import Foundation



struct AllVar: Codable {

    public var value1: String

    public var value2: String

    public var value3: String

}



func decode() -> AllVar? {

    

    var myVar : AllVar?

    var data : Data?



    // SKIP THIS let data = jsonString.data(using: .utf8, allowLossyConversion: false) // Use directly the data you get from url

    

    if let url = URL(string: "https://sheetsu.com/apis/v1.0su/4a6eb0e90aa4") {  // urlString is the url

        let urlSession = URLSession(configuration: .default).dataTask(with: url) { (readData, response, error) in

           myData = readData

        }

        

        urlSession.resume()

    }





    let jsonDecoder = JSONDecoder()

    do {

        myVar = try jsonDecoder.decode(AllVar.self, from: data!)

        return myVar

    } catch {

        print("Decode error", jsonString)

    }

    return nil

}



struct ContentView: View {

    var body: some View {

        VStack{

            Text(myVar?.value1 ?? "")

            Text(myVar?.value2 ?? "")

            Text(myVar?.value3 ?? "")

        }

    }

}



struct ContentView_Previews: PreviewProvider {

    static var previews: some View {

        ContentView()

    }

}

We don't see line numbers, so a bit tricky. I reformat with line numbers

  • //Here are the errors I received..
  • //
  • //Example of how I formatted this...
  • //Line 26: {myData = readData} → Couldn't find myData in Scope
  • //Line 38: {print("Decode error", jsonString} → Cannot find 'jsonString' in scope
  • //Line 46: {Text(myVar?.value1 ?? "")} → Cannot find 'myVar' in scope
1. import SwiftUI
2. import Foundation
3. 
4. struct AllVar: Codable {
5. 
6.     public var value1: String
7.     public var value2: String
8.     public var value3: String
9. 
10. }
11. 
12. func decode() -> AllVar? {
13. 
14.     var myVar : AllVar?
15.     var data : Data?
16. 
17.     // SKIP THIS let data = jsonString.data(using: .utf8, allowLossyConversion: false) // Use directly the data you get from url
18. 
19.     if let url = URL(string: "https://sheetsu.com/apis/v1.0su/4a6eb0e90aa4") {  // urlString is the url
20.         let urlSession = URLSession(configuration: .default).dataTask(with: url) { (readData, response, error) in
21.            myData = readData
22.         }
23. 
24.         urlSession.resume()
25.     }
26. 
27.     let jsonDecoder = JSONDecoder()
28. 
29.     do {
30.         myVar = try jsonDecoder.decode(AllVar.self, from: data!)
31.         return myVar
32.     } catch {
33.         print("Decode error", jsonString)
34.     }
35. 
36.     return nil
37. }
38. 
39. struct ContentView: View {
40. 
41.     var body: some View {
42. 
43.         VStack{
44.             Text(myVar?.value1 ?? "")
45.             Text(myVar?.value2 ?? "")
46.             Text(myVar?.value3 ?? "")
47.         }
48.     }
49. }
50. 
51. struct ContentView_Previews: PreviewProvider {
52. 
53.     static var previews: some View {
54.         ContentView()
55.     }
56. 
57. }

Change line 21 (my mistake, I corrected in forum, not in code…)

            data = readData

Change Line 33: jsonString was an earlier version of code. Remove

{print("Decode error"} 

Change Line 44: {Text(myVar?.value1 ?? "")} → Cannot find 'myVar' in scope Exact. Add line 40:

     var myVar = decode()

Hope that works now.

Got thrown a fatal error in the do catch block under let jsonDecoder ...


import SwiftUI

import Foundation



 struct AllVar: Codable {



     public var value1: String

     public var value2: String

     public var value3: String



 }



 func decode() -> AllVar? {



     var myVar : AllVar?

     var data : Data?



     // SKIP THIS let data = jsonString.data(using: .utf8, allowLossyConversion: false) // Use directly the data you get from url



     if let url = URL(string: "https://sheetsu.com/apis/v1.0su/4a6eb0e90aa4") {  // urlString is the url

         let urlSession = URLSession(configuration: .default).dataTask(with: url) { (readData, response, error) in

            data = readData

         }



         urlSession.resume()

     }



     let jsonDecoder = JSONDecoder()



     do {

         myVar = try jsonDecoder.decode(AllVar.self, from: data!) //Fatal Error Thrown here → Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

         return myVar

     } catch {

         //print("Decode error", jsonString)

     }



     return nil

 }



 struct ContentView: View {

     var myVar = decode() //Line 40 Added Code

     var body: some View {



         VStack{

             Text(myVar?.value1 ?? "")

             Text(myVar?.value2 ?? "")

             Text(myVar?.value3 ?? "")

         }

     }

 }



 struct ContentView_Previews: PreviewProvider {



     static var previews: some View {

         ContentView()

     }



}
Basic API into app to variables
 
 
Q