首页 > 解决方案 > 等待处理请求以显示信息

问题描述

我想制作一个 Swift (5.4.6) 应用程序来显示有关密码的信息。为此,我需要调用服务器来获取我想要显示的信息。但是我的应用程序不等待数据被处理,所以我得到一个想要显示零的错误。

这是我调用服务器的代码:

        
        var cryptos = Cryptos(cryptos: nil)
        
        let url = URL(string: urlString)
        let session = URLSession.shared
        let dataTask = session.dataTask(with: url!) {(data, response, error) in
            if error == nil && data != nil {
                let decoder = JSONDecoder()
                do {
                    cryptos = try decoder.decode(Cryptos.self, from: data!)
                    print(cryptos.cryptos![6].name)
                }
                catch {
                    print("Impossible de convertir les données reçues")
                }
            }
        }
            dataTask.resume()
        return cryptos
    }

这是我想将 json 解码为的结构:

struct Crypto: Codable {
    let name: String
    let symbol: String
    let price: Float
    let totalSupply: Float
    let marketCap: Float
    let change24h: Float
}

struct Cryptos: Codable {
    let cryptos: [Crypto]?
}

最后这是我认为的代码:


var lesCryptos = Cryptos()

struct CryptoList: View {
    var body: some View {
        HStack {
            NavigationView {
            }
        }
        .onAppear(perform: getAllCryptosInfos)
    }
    
}

func getAllCryptosInfos() {
    lesCryptos = Worker().getAllCryptosInfos()
    print(lesCryptos.cryptos![7].name)
}

当我想打印名称时出现错误(“lesCryptos.cryptos!”为零)

这里也是我得到的 JSON 样本:

{
  "cryptos": [
    {
      "name":"Bitcoin",
      "symbol":"BTC",
      "price":36301.41347043701,
      "totalSupply":18728856,
      "marketCap":679883945484.275,
      "change24h":0.36443243
    },
    {
      "name":"Ethereum",
      "symbol":"ETH",
      "price":2784.5450982190573,
      "totalSupply":116189845.499,"marketCap":323535864747.07007,
      "change24h":3.46116544
    }
  ]
}

标签: swiftasynchronousswiftuirequest

解决方案


首先,将您的转换struct为 aclass并设置默认值,这样就没有nil导致崩溃的值。

class Crypto: Codable {
    let name: String
    let symbol: String
    let price: Float
    let totalSupply: Float
    let marketCap: Float
    let change24h: Float

    init() {
        name = ""
        symbol = ""
        price = 0.0
        totalSupply = 0.0
        marketCap = 0.0
        change24h: 0.0
    }
}

在我的示例中,请注意init()构造函数不接受任何值。Crypto()这允许我在不传递任何值的情况下创建对象。这意味着我的对象将具有这些默认值,这在您的情况下很有用,因为您正在从nil值崩溃。

struct ExampleView: View {
     @State var someCrypto = Crypto()

     var body: some View {
         Text("\(someCrypto.name)"
              .onAppear(
                   someCrypto.name = "Example"
              )
     }
}

在这个例子中,我为我的Crypto对象使用了我的默认构造函数。这确保我的视图可以显示""someCrypto.name. 然后我onAppear用来模拟从 API 获取数据。您会注意到视图会自动更新。这是因为@State对象本质上告诉视图监听任何变化,而这些变化是two-way. 虽然在这种情况下 a实际上Text()不会使用它。two-wayTextField()

应该查找额外的阅读和学习@State @ObservedObject @ObservableObject@Published这将帮助您站起来并更快地使用 SwiftUI。


推荐阅读