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!! 
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
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. 
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ā¦
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