【问题标题】:SwiftUI - Is it possible to change an ActionSheet button text after it is displayed?SwiftUI - 是否可以在显示后更改 ActionSheet 按钮文本?
【发布时间】:2020-11-09 16:34:24
【问题描述】:

我想显示一个ActionSheet,其中包含用户可以购买的 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!)" + ")"
        }
      }
    }
  }

我在按钮创建行中指向 Text 时出现错误提示

Initializer 'init(_:)' 要求 'Binding' 符合 '字符串协议'

简而言之,我需要这个:

  1. 我显示操作表。它的按钮不包含价格。
  2. 我检索价格
  3. 操作表按钮随价格更新。

【问题讨论】:

    标签: swift swiftui observable


    【解决方案1】:

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

    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()])
            }
        }
    }
    
    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"
    }
    

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

    【讨论】:

    • 啊,我明白了。好主意。谢谢。
    猜你喜欢
    • 2020-11-26
    • 2023-04-04
    • 1970-01-01
    • 2022-09-25
    • 2020-10-30
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 2019-03-07
    相关资源
    最近更新 更多