Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SwiftUI-显示操作表按钮文本后,是否可以更改操作表按钮文本?_Swift_Swiftui_Observable - Fatal编程技术网

SwiftUI-显示操作表按钮文本后,是否可以更改操作表按钮文本?

SwiftUI-显示操作表按钮文本后,是否可以更改操作表按钮文本?,swift,swiftui,observable,Swift,Swiftui,Observable,我想显示一个操作表,其中包含用户可以购买的InApp购买对象 但我希望该表包含此类物品的价格,如: Object 1 ($1.99) Object 2 ($2.99) ... 但是价格是异步的,因为它必须从存储中检索 所以,我想这样做: struct Package { enum Packtype:String { typealias RawValue = String case obj1 = "com.example.object1"

我想显示一个
操作表
,其中包含用户可以购买的InApp购买对象

但我希望该表包含此类物品的价格,如:

Object 1 ($1.99)
Object 2 ($2.99)
...
但是价格是异步的,因为它必须从存储中检索

所以,我想这样做:

  struct Package {
    enum Packtype:String {
    typealias RawValue = String

    case obj1 = "com.example.object1"
    case obj2 = "com.example.object2"
  }

  var productID:String = ""
  @State var namePriceString:String = ""

  init(productID:String) {
    self.productID = productID
  }
}
然后,当我创建“操作表”按钮时,我执行以下操作:

var obj1 = Package(productID: Package.Packtype.obj1.rawValue)
var obj2 = Package(productID: Package.Packtype.obj2.rawValue)

self.getPrices(packages:[obj1, obj2])


let obj1Button = ActionSheet.Button.default(Text(obj1.$namePriceString)) {
  // do something with obj1
}

let obj2Button = ActionSheet.Button.default(Text(obj2.$namePriceString)) {
  // do something with obj1
}

// build the actionsheet
代码后面部分:

  func getPrices(packages:[Package]) {
    let productIDS = Set(packages.map {$0.productID})
        
    SwiftyStoreKit.retrieveProductsInfo(productIDS) { (answer) in
      if answer.invalidProductIDs.first != nil { return }
      
      let results = answer.retrievedProducts
      if results.count == 0 { return }
      
      for result in answer {
        if let package = packages.filter({ ($0.productID == result.productIdentifier) }).first {
          package.namePriceString = result.localizedTitle + "(" + "\(result.localizedPrice!)" + ")"
        }
      }
    }
  }
我在指向按钮创建行上的
文本时出错

初始值设定项“init(:)”要求“Binding”符合 “StringProtocol”

简而言之,我需要这个:

  • 我显示行动表。它的按钮没有价格
  • 我收回价格
  • Actionsheet按钮随价格更新

  • 一种可能的解决方案是在
    完成处理程序中返回价格,然后才显示操作表:

    struct ContentView: View {
        @State var showActionSheet = false
        @State var localizedPrices = [Package: String]()
    
        var body: some View {
            Button("Get prices") {
                getPrices(packages: Package.allCases, completion: {
                    localizedPrices = $0
                    showActionSheet = true
                })
            }
            .actionSheet(isPresented: $showActionSheet) {
                let buttons = localizedPrices.map { package, localizedPrice in
                    ActionSheet.Button.default(Text(localizedPrice), action: { buy(package: package) })
                }
                return ActionSheet(title: Text("Title"), message: Text("Message"), buttons: buttons + [.cancel()])
            }
        }
    }
    

    这可以通过加载动画等进行进一步调整。

    ahhh,我明白了。好主意。谢谢
    func getPrices(packages: [Package], completion: @escaping ([Package: String]) -> Void) {
        // simulates an asynchronous task, should be replaced with the actual implementation
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            let localizedPrices = Dictionary(uniqueKeysWithValues: packages.map { ($0, "\(Int.random(in: 1 ..< 100))") })
            completion(localizedPrices)
        }
    }
    
    func buy(package: Package) {
        print("Buying \(package.rawValue)")
    }
    
    enum Package: String, CaseIterable {
        case obj1 = "com.example.object1"
        case obj2 = "com.example.object2"
    }