使用 swift 中的完成从闭包中提取数据
Extract data from closure using completion in swift
首先,这是我第一次尝试 Swift,所以我不太确定自己在做什么。我正在学习,现在遇到了障碍。
我正在尝试实现一个 WatchOS 应用程序,它将在设定的计时器上调用 API 来跟踪某些加密货币价格的波动。
我已经想出如何进行 API 调用并将 JSON 解析到可以打印数据的点,但我正在努力将其从闭包中取出并且到我的界面。我知道执行此操作的正确方法是使用完成处理程序,但我似乎无法深入了解如何在这种情况下使其工作。
如有任何帮助,我们将不胜感激
import SwiftUI
var refresh = bitcoin()
var btc: String = refresh
var eth: String = "ETH"
var doge: String = "DOGE"
struct ContentView: View {
var body: some View {
VStack(alignment: .leading ){
Label("\(btc)", image: "eth").padding(.vertical, 10.0)
Label("\(eth)", image: "eth").padding(.vertical, 10.0)
Label("\(doge)", image: "doge").padding(.vertical, 10.0)
}
.scaledToFill()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
struct responseData: Codable{
let data: Response?
}
struct Response: Codable{
var id: String
var rank: String
var symbol: String
var name: String
var supply: String
var maxSupply: String
var marketCapUsd: String
var volumeUsd24Hr: String
var priceUsd: String
var changePercent24Hr: String
var vwap24Hr: String
}
func bitcoin() -> String{
var result: String = "btc"
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
result = (response.data?.priceUsd)!
print(result)
}
task.resume()
return result
}
有很多方法可以实现你想要的,一种方法是使用“ObservableObject”。尝试这样的事情:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class CoinModel: ObservableObject {
@Published var btcPriceUsd = "not yet available"
@Published var ethPriceUsd = "not yet available"
@Published var dogePriceUsd = "not yet available"
}
struct ContentView: View {
@StateObject var coins = CoinModel()
var body: some View {
VStack(alignment: .leading ){
Label("\(coins.btcPriceUsd)", image: "btc").padding(.vertical, 10.0)
Label("\(coins.ethPriceUsd)", image: "eth").padding(.vertical, 10.0)
Label("\(coins.dogePriceUsd)", image: "doge").padding(.vertical, 10.0)
}
.scaledToFill()
.onAppear {
// bitcoin()
bitcoin2 { price in
coins.btcPriceUsd = price
}
}
}
func bitcoin() {
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
return
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
if let respData = response.data {
DispatchQueue.main.async {
coins.btcPriceUsd = respData.priceUsd
}
}
}
task.resume()
}
}
编辑:如果你真的想使用完成,那么试试这个:
func bitcoin2(completion: @escaping (String) -> Void) {
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
return completion("")
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
if let respData = response.data {
DispatchQueue.main.async {
completion(respData.priceUsd)
}
}
}
task.resume()
}
首先,这是我第一次尝试 Swift,所以我不太确定自己在做什么。我正在学习,现在遇到了障碍。
我正在尝试实现一个 WatchOS 应用程序,它将在设定的计时器上调用 API 来跟踪某些加密货币价格的波动。
我已经想出如何进行 API 调用并将 JSON 解析到可以打印数据的点,但我正在努力将其从闭包中取出并且到我的界面。我知道执行此操作的正确方法是使用完成处理程序,但我似乎无法深入了解如何在这种情况下使其工作。
如有任何帮助,我们将不胜感激
import SwiftUI
var refresh = bitcoin()
var btc: String = refresh
var eth: String = "ETH"
var doge: String = "DOGE"
struct ContentView: View {
var body: some View {
VStack(alignment: .leading ){
Label("\(btc)", image: "eth").padding(.vertical, 10.0)
Label("\(eth)", image: "eth").padding(.vertical, 10.0)
Label("\(doge)", image: "doge").padding(.vertical, 10.0)
}
.scaledToFill()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
struct responseData: Codable{
let data: Response?
}
struct Response: Codable{
var id: String
var rank: String
var symbol: String
var name: String
var supply: String
var maxSupply: String
var marketCapUsd: String
var volumeUsd24Hr: String
var priceUsd: String
var changePercent24Hr: String
var vwap24Hr: String
}
func bitcoin() -> String{
var result: String = "btc"
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
result = (response.data?.priceUsd)!
print(result)
}
task.resume()
return result
}
有很多方法可以实现你想要的,一种方法是使用“ObservableObject”。尝试这样的事情:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class CoinModel: ObservableObject {
@Published var btcPriceUsd = "not yet available"
@Published var ethPriceUsd = "not yet available"
@Published var dogePriceUsd = "not yet available"
}
struct ContentView: View {
@StateObject var coins = CoinModel()
var body: some View {
VStack(alignment: .leading ){
Label("\(coins.btcPriceUsd)", image: "btc").padding(.vertical, 10.0)
Label("\(coins.ethPriceUsd)", image: "eth").padding(.vertical, 10.0)
Label("\(coins.dogePriceUsd)", image: "doge").padding(.vertical, 10.0)
}
.scaledToFill()
.onAppear {
// bitcoin()
bitcoin2 { price in
coins.btcPriceUsd = price
}
}
}
func bitcoin() {
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
return
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
if let respData = response.data {
DispatchQueue.main.async {
coins.btcPriceUsd = respData.priceUsd
}
}
}
task.resume()
}
}
编辑:如果你真的想使用完成,那么试试这个:
func bitcoin2(completion: @escaping (String) -> Void) {
var request = URLRequest(url: URL(string: "https://api.coincap.io/v2/assets/bitcoin")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
return completion("")
}
let response = try! JSONDecoder().decode(responseData.self, from: data)
if let respData = response.data {
DispatchQueue.main.async {
completion(respData.priceUsd)
}
}
}
task.resume()
}