CSV Data Into App + Search

With regard to the url to download the file, what most of us do is assign that entire url to a string and then pass that into the function getCSV(). For example:

let sourceFileUrl = "https://firms.modaps.eosdis.nasa.gov/data/active_fire/c6/csv/MODIS_C6_USA_contiguous_and_Hawaii_24h.csv"
getCSV(urlString: sourceFileUrl)

Scope errors are usually caused by referring to a variable, constant or method that does not exist within the current environment.

If you are getting Scope errors for URL, URLRequest and URLSession it may be because you are using Playground and there is a missing import statement at the top of the Playground source file. You should have at least

import Foundation.

Ohh! I understand. What I have then, is

import Foundation

func getCSV(urlString: String) {

    var returnedData: [File] = []
    let url = URL(string: urlString)
    let task = URLSession.shared.downloadTask(with: url!) { (localURL, urlResponse, error) in

        if let localURL = localURL {

            if let urlContents = try? String(contentsOf: localURL)  {

                let allRecords = urlContents.components(separatedBy: "\n")

                //  Remove CSV header line

                let records = allRecords.dropFirst()

                //  Process all the records

                for record in records {

                    if record != "" {

                        //  Split each record into an array of columns

                        let columns = record.components(separatedBy: ",")

                        //  Create the array entry

                        let newEntry = File(id: UUID(),

                                            latitude: Double(columns[0])! as Double,
                                            longitude: Double(columns[1])! as Double,
                                            brightness: Double(columns[2])! as Double,
                                            scan: Double(columns[3])! as Double,
                                            track: Double(columns[4])! as Double,
                                            acq_date: columns[5] as String,
                                            acq_time: Int(columns[6])! as Int,
                                            satellite: columns[7] as String,
                                            confidence: Int(columns[8])! as Int,
                                            version: columns[9] as String,
                                            bright_t31: Double(columns[10])! as Double,
                                            frp: Double(columns[11])! as Double,
                                            daynight: columns[12] as String
                        )

                        returnedData.append(newEntry)

                        print("Data separated into Columns")

                        let dataString = "'" + columns.joined(separator: "', '") + "'"

                        print(dataString)

                    }

                }



                DispatchQueue.main.async {

                    self.files = returnedData

                }



            }

        }

    }

    task.resume()

}

let sourceFile = "https://firms.modaps.eosdis.nasa.gov/data/active_fire/c6/csv/MODIS_C6_USA_contiguous_and_Hawaii_24h.csv"

getCSV(urlString: sourceFile)

I got a scope error for the declaration of the returnedData array; is it because Iā€™m in a playground and Swift doesnā€™t support delegating data into a file here? The same scope error occurs for the declaration of the constant: newEntry with ā€œcannot find ā€˜Fileā€™ in scopeā€. Lastly, ā€œself.filesā€ returns the same scope error, except with ā€œcannot find ā€˜Selfā€™ in scopeā€. How should I proceed to fix these errors? Thank you so much!! :smiley:

You need to include the struct that defines your File above your function so that it is in ā€œScopeā€ meaning in the same code file.

Comment out the 3 lines that make up the DispatchQueue code because that wont be needed in Playground. That was there for my testing as I was placing some of the data into a tableView so that I knew everything was working.

With those additions and changes it should work.

1 Like

Oh it does! Yay, finally no more errors :slight_smile: So now, how do I call the array? I ran the playground with

  let sourceFileUrl = "https://firms.modaps.eosdis.nasa.gov/data/active_fire/c6/csv/MODIS_C6_USA_contiguous_and_Hawaii_24h.csv"

getCSV(urlString: sourceFileUrl)

How do I get either all the data from my csv to show up in the console or a certain row? Thank you so much again!!

The group of statements in the code:

print("Data separated into Columns")
let dataString = "'" + columns.joined(separator: "', '") + "'"
print(dataString)

should be printing eacg record to the console as it is created.
If you are not seeing anything in the Playground window at the bottom then you may have to activate it.

From the Xcode menu select View > Debug Area > Activate Console.

Oh, hmā€¦ My Console is activated but after I call getCSV, nothing appearsā€¦ Iā€™ll attach my code below, maybe I didnā€™t format my function call correctly? Iā€™m pretty sure the call works though, so Iā€™m not sure why itā€™s not printingā€¦ It should print into the bottom panel (the console Iā€™m assuming) of the playground under where I click run, correct? I probably overlooked something super obvious. Sorry for making this so difficult.

import Foundation

struct File: Identifiable, Decodable {
    var id: UUID?
    var latitude: Double
    var longitude: Double
    var brightness: Double
    var scan: Double
    var track: Double
    var acq_date: String
    var acq_time: Int
    var satellite: String
    var confidence: Int
    var version: String
    var bright_t31: Double
    var frp: Double
    var daynight: String
    
    init(id: UUID?, latitude: Double, longitude: Double, brightness: Double, scan: Double, track: Double, acq_date: String, acq_time: Int, satellite: String, confidence: Int, version: String, bright_t31: Double, frp: Double, daynight: String)
{
    self.id = id
    self.latitude = latitude
    self.longitude = longitude
    self.brightness = brightness
    self.scan = scan
    self.track = track
    self.acq_date = acq_date
    self.acq_time = acq_time
    self.satellite = satellite
    self.confidence = confidence
    self.version = version
    self.bright_t31 = bright_t31
    self.frp = frp
    self.daynight = daynight
    }
}


func getCSV(urlString: String) {

        var returnedData: [File] = []
        let url = URL(string: urlString)
        let task = URLSession.shared.downloadTask(with: url!) { (localURL, urlResponse, error) in

            if let localURL = localURL {

                if let urlContents = try? String(contentsOf: localURL)  {
                    //  Split the file into an array of records
                    let allRecords = urlContents.components(separatedBy: "\n")
                    //  Remove CSV header line
                    let records = allRecords.dropFirst()
                    //  Process all the records
                    for record in records {

                        if record != "" {

                            //  Split each record into an array of columns

                            let columns = record.components(separatedBy: ",")

                            //  Create the array entry

                            let newEntry = File(id: UUID(),

                                                latitude: Double(columns[0])! as Double,

                                                longitude: Double(columns[1])! as Double,

                                                brightness: Double(columns[2])! as Double,

                                                scan: Double(columns[3])! as Double,

                                                track: Double(columns[4])! as Double,

                                                acq_date: columns[5] as String,

                                                acq_time: Int(columns[6])! as Int,

                                                satellite: columns[7] as String,

                                                confidence: Int(columns[8])! as Int,

                                                version: columns[9] as String,

                                                bright_t31: Double(columns[10])! as Double,

                                                frp: Double(columns[11])! as Double,

                                                daynight: columns[12] as String

                            )

                            returnedData.append(newEntry)

                            print("Data separated into Columns")

                            let dataString = "'" + columns.joined(separator: "', '") + "'"

                            print(dataString)

                        }

                    }

                   // DispatchQueue.main.async {

                      //  self.files = returnedData

                    }
                }

            }

        }

let sourceFileUrl = "https://firms.modaps.eosdis.nasa.gov/data/active_fire/c6/csv/MODIS_C6_USA_contiguous_and_Hawaii_24h.csv"

getCSV(urlString: sourceFileUrl)

Thank you Mr. Parker for all your time. :grin:

This works for me in a playground I created:

import Foundation

struct File: Identifiable, Decodable {
    var id: UUID?
    var latitude: Double
    var longitude: Double
    var brightness: Double
    var scan: Double
    var track: Double
    var acq_date: String
    var acq_time: Int
    var satellite: String
    var confidence: Int
    var version: String
    var bright_t31: Double
    var frp: Double
    var daynight: String

    init(id: UUID?, latitude: Double, longitude: Double, brightness: Double, scan: Double, track: Double, acq_date: String, acq_time: Int, satellite: String, confidence: Int, version: String, bright_t31: Double, frp: Double, daynight: String)
{
    self.id = id
    self.latitude = latitude
    self.longitude = longitude
    self.brightness = brightness
    self.scan = scan
    self.track = track
    self.acq_date = acq_date
    self.acq_time = acq_time
    self.satellite = satellite
    self.confidence = confidence
    self.version = version
    self.bright_t31 = bright_t31
    self.frp = frp
    self.daynight = daynight
    }
}




func getCSV(urlString: String) {
    var returnedData: [File] = []
    let url = URL(string: urlString)
    let task = URLSession.shared.downloadTask(with: url!) { (localURL, urlResponse, error) in
        if let localURL = localURL {
            if let urlContents = try? String(contentsOf: localURL)  {
                let allRecords = urlContents.components(separatedBy: "\n")
                //  Remove CSV header line
                let records = allRecords.dropFirst()
                //  Process all the records
                for record in records {
                    if record != "" {
                        //  Split each record into an array of columns
                        let columns = record.components(separatedBy: ",")
                        //  Create the array entry
                        let newEntry = File(id: UUID(),
                                            latitude: Double(columns[0])! as Double,
                                            longitude: Double(columns[1])! as Double,
                                            brightness: Double(columns[2])! as Double,
                                            scan: Double(columns[3])! as Double,
                                            track: Double(columns[4])! as Double,
                                            acq_date: columns[5] as String,
                                            acq_time: Int(columns[6])! as Int,
                                            satellite: columns[7] as String,
                                            confidence: Int(columns[8])! as Int,
                                            version: columns[9] as String,
                                            bright_t31: Double(columns[10])! as Double,
                                            frp: Double(columns[11])! as Double,
                                            daynight: columns[12] as String
                        )
                        returnedData.append(newEntry)
                        print("Data separated into Columns")
                        let dataString = "'" + columns.joined(separator: "', '") + "'"
                        print(dataString)
                    }
                }
                //                DispatchQueue.main.async {
                //
                //                    self.files = returnedData
                //
                //                }

            }
        }
    }
    task.resume()

}

let sourceFile = "https://firms.modaps.eosdis.nasa.gov/data/active_fire/c6/csv/MODIS_C6_USA_contiguous_and_Hawaii_24h.csv"
getCSV(urlString: sourceFile)

2 Likes

Oh! I must have forgotten to comment out a brace or something. Thank you so much, it works! Yay!!! One last thing, is there a way to print a specific column of data or columns i.e. if I wanted to print the Latitude, Longitude, and FRP? Iā€™m assuming print(returnedData[0]) wonā€™t work or anythingā€¦ :joy: Thanks so much again @Chris_Parker!!

This is now the point that you need to consider taking on a course to give you the Foundation to understand how to integrate this kind of data retrieval into an App for display in a UI.

1 Like

Understood. @Chris_Parker I would like to sincerely thank you for all the time and assistance youā€™ve given me here. It has proven to be the most valuable guidance at the moment for me in my Swift and coding Development. I truly, truly thank you for all your help. I wish you the best, and again, thank you for all of your attention. Iā€™ll continue with your advice, and maybe even by CWC + :slight_smile:

  • BananaNinja :grinning: :innocent:
1 Like