Swift 如何从单例中的异步内容更新接口元素

Swift 如何从单例中的异步内容更新接口元素,swift,swiftui,Swift,Swiftui,我正在用SwiftUI开发我的第一个应用程序,我的大脑还没有完全理解某些事情 我必须在界面上显示inapp购买的价格、标题和说明 我有一个这样的单例模型,在应用程序启动时加载 class Packages:ObservableObject { enum Package:String, CaseIterable { typealias RawValue = String case package1 = "com.example.package1" c

我正在用SwiftUI开发我的第一个应用程序,我的大脑还没有完全理解某些事情

我必须在界面上显示inapp购买的价格、标题和说明

我有一个这样的单例模型,在应用程序启动时加载

class Packages:ObservableObject {
  
enum Package:String, CaseIterable {
  typealias RawValue = String
    
  case package1 = "com.example.package1"
  case package2 = "com.example.package2"
  case package3 = "com.example.package3"
}
  
struct PurchasedItem {
  var productID:String?
  var localizedTitle:String = ""
  var localizedDescription:String = ""
  var localizedPrice:String = ""
}
  
static let sharedInstance = Packages()
  
@Published var purchasedItems:[PurchasedItem] = []

func getItem(_ productID:String) -> PurchasedItem? {
  return status.filter( {$0.productID == productID } ).first
}  

func getItemsAnync() {
  // this will fill `purchasedItems` asynchronously
}
purchasedItems
数组将填充异步的
PurchasedItem
s,因为price、title和description的值来自应用商店

同时,在界面的另一部分,我在视图上显示按钮,如下所示:

var  buttonPackage1String:String {

  let item = Packages.sharedInstance.getItem(Packages.Package.package1.rawValue)!

  let string = """
    \(umItem.localizedTitle) ( \(umItem.localizedPrice) ) \
    \(umItem.localizedDescription) )
    """

  return string
}

// inside var Body

    Button(action: {
      // purchase selected package
    }) {
      Text(buttonPackage1String)
        .padding()
        .background(Color.green)
        .foregroundColor(.white)
        .padding()
  }
看到我的问题了吗

buttonPackage1String
由名为
purchasedItems
的数组中的标题、描述和价格构建而成,该数组存储在一个单例中,该数组以异步方式填充,最初为空

因此,在显示视图时,可能尚未检索到所有值,但最终会检索到


是否有办法在检索到值后更新按钮?

SwiftUI不遵守可计算属性。我们必须为此引入显式状态,并在依赖的动态数据更改后更新它

大概

@ObservedObject var packages: Packages

...

@State private var title: String = ""

...

    Button(action: {
      // purchase selected package
    }) {
      Text(title)
    }
    .onChange(of: packages.purchasedItems) { _ in
       self.title = buttonPackage1String          // << here !!
    }
@ObservedObject变量包:包
...
@国家私有变量标题:String=“”
...
按钮(操作:{
//购买所选套餐
}) {
正文(标题)
}
.onChange(of:packages.purchasedItems){in

self.title=buttonPackage1String/下面是一个小的伪代码,我不确定它是否适合您的项目,但可能会给您一些提示

Packages.sharedInstance
  .$purchasedItems //add $ to get the `Combine` Subject of variable
  .compactMap { $0.firstWhere { $0.id == Packages.Package.package1.rawValue } } //Find the correct item and skip nil value
  .map { "\($0.localizedTitle) ( \($0.localizedPrice) ) \ \($0.localizedDescription) )" }
  .receive(on: RunLoop.main) // UI updates
  .assign(to: \.buttonTitleString, on: self) //buttonTitleString is a @Published variable of your View model
  .store(in: &cancellables) //Your cancellable collector
Combine
框架知识是使用SwiftUI的必备知识。

这也可能有助于您: