Day-24-stockPickerD3
- Day 3 of the StockPickerChallenge
- May 2, 2021
add a +
symbol to link to a function to add a new stock.
.navigationBarTitle("Your Stocks")
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button("+") {
self.showingAlert.toggle()
}
}//ToolBargroup
}//toolbar
add a function that will download a new stock
This was considerably more challenging as it involves the Apps architecture. It would make sense that this function should be part of the DataServices.swift file but that is currently decoding my local json (in app) file with a few example Stocks. And the StockModel.swift then grabs that data and sets it to an array of Stocks.
Perhaps I could still put this function in dataServices but I have it currently in StockModel so that I can just call it directly from model in my views.
func getRemoteData(ticker: String) {
//let ticker = "OTTR"
// Set up url with ticker variable
let url = URL(string: "https://financialmodelingprep.com/api/v3/quote/\(ticker)?apikey=0f5eedfec854e23eb12dc71fbaa4dab7")
//create the url request
var request = URLRequest(url: url!)
// this code is from the example they provided from the API and returns data.
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
guard error == nil else {
print(error!)
return
}//Guard
guard let data = data else {
print("Data is empty")
return
}//Guard
// process the data from the url request as we would from file and append to [Stocks] array
do {
// decode data with a JSONDecoder
let decoder = JSONDecoder()
//
//pass in type
do {
let stockData = try decoder.decode([Stock].self, from: data)
// add unique IDs
for r in stockData {
r.id = UUID()
print(r.name)
}//for
// Return the stocks
DispatchQueue.main.async { // required to run on the main thread to execute this.
self.stocks = self.stocks + stockData
}
} catch {
print(error)
}//do-catch
}
}//task
task.resume()
}
I spent a lot of time realizing that the URLSession.shared.dataTask
already gives us a data variable that we can use directly in the JSONdecoder. I kept trying to convert the json into a Data object, which apparently I already had.
append added stock to stock array.
Turns out if you want to modify an environmentObject you have to run it on the main thread so I had to wrap this modification in a DispatchQueue.main.async
block
DispatchQueue.main.async { // required to run on the main thread to execute this.
self.stocks = self.stocks + stockData
}
add a popup to specify which ticker symbol to download
I really wanted to include an alert and @Chris_Parker has a great solution.
Chris Parker’s swiftUI alert
I went ahead and just made an if else statement that either shows the popup or the list of stocks.
TODO
- Why is the textEntered not updating unless done twice?
- I needed to add the model environmentObject to the CustomAlert View and then run the model.getRemote function from there and it updated as expected.
- delete a stock using a touch gesture drag to the right