变量未在 Swift 中更新 [英] Variable is not getting updated in Swift

查看:28
本文介绍了变量未在 Swift 中更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 SwiftUI 应用程序有一个解析 JSON 数据的类.正如您从 print 附近的评论中看到的那样,我不明白 print("return: " + self.productName) 行打印变量仍然为空(基本上是初始化的).为什么变量在 if 块内部更新,而不在外部更新?

My SwiftUI app has a class which parses JSON Data. As you can see from the comments near the print, I do not understand while the line print("return: " + self.productName) print the variable still empty (basically the initialized one). Why is the variable updated inside the if block, but not outside?

有什么想法吗?谢谢.

class ProductDecoer: ObservableObject {

  @Published var productName: String = ""

  func checkBarCode(barcode: String) -> String {

    let api = <url>
    let barcode = barcode
    let format = ".json"
    let url = URL(string: api + barcode + format)

    URLSession.shared.dataTask(with: url!) { [self] data, response, error in
      if let data = data {
        if let jsonString = String(data: data, encoding: .utf8) {
          productName = self.getProductInfo(json: jsonString)
          print("checkBarCode: " + self.productName) // --> print correctly
        }
      }
    }.resume()

    self.productName = productName
    print("return: " + self.productName) // --> is empty
    return self.productName
  }

  func getProductInfo(json: String) -> String {
    let jsonData = json.data(using: .utf8)!
    let productInfo: ProductInfo = try! JSONDecoder().decode(ProductInfo.self, from: jsonData)
    self.productName = productInfo.product_name
    print("AAA: " + self.productName)
    print("Prodotto: " + productInfo.product_name)

    productName = productInfo.product_name
    print("CC: " + productName)

    return productName
  }

  struct ProductInfo: Codable {

    var code: String
    var product_name: String

    enum CodingKeys: String, CodingKey {
      case code
      case product

      enum ProductCodingKeys: String, CodingKey {
        case product_name
      }
    }

    init(from decoder: Decoder) throws {
      let rootContainer = try decoder.container(keyedBy: CodingKeys.self)
      let productContainer = try rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)

      code = try rootContainer.decode(String.self, forKey: .code)
      product_name = try productContainer.decode(String.self, forKey: .product_name)

      print("BB: " + product_name)
    }

    func encode(to encoder: Encoder) throws {
      var rootContainer = encoder.container(keyedBy: CodingKeys.self)
      var productContainer = rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)

      try rootContainer.encode(code, forKey: .code)
      try productContainer.encode(product_name, forKey: .product_name)
    }
  }

}

推荐答案

由于您的 ProductDecoer 类符合 ObservableObject 并且属性 productName 是使用@Publisher 发布您不需要从函数 checkBarCode 返回任何内容,因此将函数的签名更改为

Since your ProductDecoer class conforms to ObservableObject and the property productName is published using @Publisher you don't need to return anything from the function checkBarCodeso change the signature of the function to

func checkBarCode(barcode: String) { ... }

并删除 .resume() 之后的所有内容.

and remove everything after .resume() in it.

然后在您的 SwiftUI 视图中为该类创建一个属性并使用 @ObservedObject 属性

Then in your SwiftUI view you create a property for the class and use the @ObservedObject property

@ObservedObject var decoder = ProductDecoer()

下面是一个完整但简单的视图示例,当按下按钮时,它将请求文本字段中给出的条形码的产品名称.下载信息后,将设置发布的属性 productName 并且视图将显示它.

Below is a complete but simple example of a view that will request the product name for the bar code given in a text field when a button is pressed. Once the information has been downloaded the published property productName will be set and the view will display it.

struct ContentView: View {
    @ObservedObject var decoder = ProductDecoer()
    @State private var barCode: String = ""
    var body: some View {
        VStack(alignment: .leading) {
            TextField("Bar code", text: $barCode)
            Text(decoder.productName)

            Button {
                decoder.checkBarCode(barcode: barCode)
            }
            label: {
                Text("Load")
            }
        }
        .padding()
    }
}  

这篇关于变量未在 Swift 中更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆