不符合 String 协议 SwiftUI Picker View

Cry*_*tal 1 swiftui

我有一个简单的基础struct,我将在此基础上进行构建。现在它有一个字段,一个 Int。

struct Card: CustomStringConvertible  {
  let value: Int

  init(value: Int) {
    self.value = value
  }

  var description: String {
    return "\(String(value))"
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我这样做,我就会得到卡来打印它的价值

let c = Card(value: 1)
print(c)
Run Code Online (Sandbox Code Playgroud)

现在,如果我将卡片数组放入 CardController 中,如下所示:

class CardController: ObservableObject {
  @Published
  var cards: [Card] = [
    Card(value: 1),
    Card(value: 2),
    Card(value: 3)
  ]

Run Code Online (Sandbox Code Playgroud)
Picker(selection: $selectedCardValue, label: Text("Choose a card")) {
        ForEach(0..<cardController.cards.count) {
          Text(self.cardController.cards[$0])
        }
      }
      Text("You selected \(selectedCardValue)")
Run Code Online (Sandbox Code Playgroud)

我会得到错误Initializer 'init(_:)' requires that 'Card' conform to StringProtocol。我不确定为什么会收到此错误。如果我只是将 更改为和 值cards的类型,则代码可以正常工作。[String]["1", "2", "3"]

知道这里出了什么问题吗?

Joh*_* M. 8

正如 E.Coms 指出的,解决方案是使用以下方法之一:

Text(self.cardController.cards[$0].description)

Text(String(describing: self.cardController.cards[$0]))

下面解释了 为什么必须在Text初始化程序中执行此操作,而不是在print().


查看两个初始化程序Text

init(verbatim content: String)文档

init<S>(_ content: S) where S : StringProtocol文档

您必须传递 aString或 a Substring,这是唯一符合 的两种类型StringProtocol。在这种情况下,即使您的类型符合CustomStringConvertible,您仍然传递Card.


将此与类似函数进行对比print

func print(_ items: Any..., separator: String = " ", terminator: String = "\n")文档

请注意,该print函数的参数由 表示Any,其解释为

Any 可以表示任何类型的实例,包括函数类型。

然后 print 函数将您传递给它的任何内容转换为String

每个项目的文本表示与通过调用 String(item) 获得的文本表示相同。

String有一个初始化程序,它采用符合该属性的类型CustomStringConvertible并返回该description属性。


print(Card())所以你可以写和不写的原因Text(Card()是因为 print 函数有一个中间步骤String可以理解你对 的一致性CustomStringConvertible,但Text不能。如果Text允许您传递任何类型,它会更加模糊(“这种类型的文本表示是什么?”不一定立即显而易见,因为它取决于一组分层协议),并且 SwiftUI 需要做更多工作系统,它已经做了很多事情。