变量未在 Swift 中更新 [英] Variable is not getting updated in 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 checkBarCode
so 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屋!