Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

swift - API Request not showing on simulator when button pressed

I am trying to get stock data from the website with an API Request. In that example I want to extract the symbol of a stock, by pressing the button. The code has no errors itself, but I does not display the API request and providing the symbol in that case AAPL to the simulator. Do you have any idea of what am I doing wrong?

struct Helper: View {
    @State private var quoteData: QuoteData?
    var body: some View {
        HStack {
            Spacer()
            
            VStack(alignment: .leading) {
                Text(quoteData?.symbol ?? ".")

                Button(action: loadData) {
                    Text("Press here")
                }
                
            }
        }
        .onAppear(perform: loadData)
    }
    


    private func loadData() {
        guard let url = URL(string: "https://financialmodelingprep.com/api/v3/quote/AAPL?apikey=836129f3de1b99ff975e910a4541254d") else {
            return
        }
        URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data else { return }
            if let decodedData = try?JSONDecoder().decode(QuoteData.self, from: data) {
                DispatchQueue.main.async {
                    self.quoteData = decodedData
                }
            }
        }.resume()
    }
    
}

Here i just try to take the symbol from the stock which is of type string. The API adress does not have an id.

struct QuoteData: Decodable {
    var symbol: String?
}

struct Helper_Previews: PreviewProvider {
    static var previews: some View {
        Helper()
    }
}
question from:https://stackoverflow.com/questions/65894188/api-request-not-showing-on-simulator-when-button-pressed

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I am going to refer you to this answer for a more detailed description. I will fully admit to stealing the work of @nicksarno in crafting this answer. Please read the entire answer as he and I give this issue a pretty thorough response. I would have just referred you there, but there is a lot to unpack here in addition.

First, please make sure you change your API key. You should not EVER post a private API key. You pay (or will pay) for access to that data.

On to the answer. Your request code was incorrect. What I have posted is a modern request using Combine that is fully discussed in the answer link I posted. In addition, I corrected your decoder by simply running it through QuickType, which is also referenced in the answer.

Parsing JSON is a pain, and if nothing else, start with Quicktype or some other parser. In this case, the JSON data, even though you only requested one stock, was an array. You decoder has to exactly match the structure of the JSON, though it does not need to have every element of the JSON. It also has to conform to the Codable protocol.

import SwiftUI

struct Helper: View {
    @State private var symbol: String?
    var body: some View {
        HStack {
            Spacer()
            
            VStack(alignment: .leading) {
                Text(symbol ?? ".")
                
                Button(action: { loadData() }) {
                    Text("Press here")
                }
                
            }
        }
    }
    
    
    
    private func loadData() {
        guard let url = URL(string: "https://financialmodelingprep.com/api/v3/quote/AAPL?apikey=836129f3de1b99ff975e910a4541254d") else {
            return
        }
        URLSession.shared.dataTaskPublisher(for: url)
            // fetch on background thread
            .subscribe(on: DispatchQueue.global(qos: .background))
            // recieve response on main thread
            .receive(on: DispatchQueue.main)
            // ensure there is data
            .tryMap { (data, response) in
                guard
                    let httpResponse = response as? HTTPURLResponse,
                    httpResponse.statusCode == 200 else {
                    throw URLError(.badServerResponse)
                }
                return data
            }
            // decode JSON data to QuoteDecoder
            .decode(type: QuoteDecoder.self, decoder: JSONDecoder())
            // Handle results
            .sink { (result) in
                // will return success or failure
                print("completion: (result)")
            } receiveValue: { (value) in
                // if success, will return QuoteDecoder
                // here you can update your view
                print("value: (value)")
                // you can handle your data however you need to. Remember that it is an array of QuoteData.
                if let quote = value.first {
                    self.symbol = quote.symbol
                }
            }
            // After recieving response, the URLSession is no longer needed & we can cancel the publisher
            .cancel()
    }
}

struct QuoteData: Codable {
    let symbol, name: String?
    let price, changesPercentage, change, dayLow: Double?
    let dayHigh, yearHigh, yearLow: Double?
    let marketCap: Int?
    let priceAvg50, priceAvg200: Double?
    let volume, avgVolume: Int?
    let exchange: String?
    let quoteDatumOpen, previousClose, eps, pe: Double?
    let earningsAnnouncement: String?
    let sharesOutstanding, timestamp: Int?
    
    enum CodingKeys: String, CodingKey {
        case symbol, name, price, changesPercentage, change, dayLow, dayHigh, yearHigh, yearLow, marketCap, priceAvg50, priceAvg200, volume, avgVolume, exchange
        case quoteDatumOpen = "open"
        case previousClose, eps, pe, earningsAnnouncement, sharesOutstanding, timestamp
    }
}

typealias QuoteDecoder = [QuoteData]

struct Helper_Previews: PreviewProvider {
    static var previews: some View {
        Helper()
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...