swift appendInterpolation的使用不明确-为什么?

tktrz96b  于 2023-05-28  发布在  Swift
关注(0)|答案(1)|浏览(158)

当使用CustomStringConvertible结构时,常规的String插值可以正常工作,但是因为Text(SwiftUI)使用LocalizedString插值,所以它不能正常工作,并且需要您完全追加.description,或者使用Text(verbatim: ...)Text(String(describing...))
直到(?)Apple协调String和LocalizedString的插值,创建一个扩展以直观的方式在CustomStringConvertibles上进行插值似乎是一个足够简单的解决方案。例如

extension LocalizedStringKey.StringInterpolation {
   public mutating func appendInterpolation<S: CustomStringConvertible>(_ convertible: S) {
      self.appendInterpolation(convertible.description)
   }
}

这意味着文本按预期工作。例如

struct Car: CustomStringConvertible {
    var model: String
    var description: String 
}
var car: Car = Car(model: "Ford Ka", description: "Dubiously named oddity")

在你看来:Text("\(car)")输出如上所述的描述。太好了!

但是...任何其他文本插值现在都会产生错误:* “模糊使用appendInterpolation”* 例如

let a = 1
Text("\(a)").   <--- error: Ambiguous use of appendInterpolation

删除上面的扩展可以立即解决该错误。我很想知道为什么,因为我已经为此挠头了一段时间。
谢谢!

ldxq2e6h

ldxq2e6h1#

这个调用在appendInterpolation重载和this builtin overload重载之间是不明确的,后者需要一个_FormatSpecifiable
由于这两个方法都是通用的,Swift无法决定哪一个“更好”,并告诉你它是模糊的。
你可以让你的方法非泛型化:

extension LocalizedStringKey.StringInterpolation {
   public mutating func appendInterpolation(_ convertible: any CustomStringConvertible) {
      self.appendInterpolation(convertible.description)
   }
}

这会导致Swift总是更喜欢你的方法,这可能会扰乱一些本地化的字符串键。如果您有Text("This is a number: \(someInt)")Text将查找本地化键“This is a number:但是如果它调用你的方法,它不知道用%lld替换插值,从我的实验来看,它用%@替换了它。
为了好玩,让我们试试符合_FormatSpecifiable!(由于它的前缀是下划线,因此这是不稳定的API,可能会中断)

extension Car: _FormatSpecifiable {
    var _arg: String {
        description
    }
    
    var _specifier: String {
        "%@"
    }
}

_specifier属性可能用于计算实际的本地化字符串键。例如,如果它是"I have a \(car)",而_specifier返回%@,则本地化键将是"I have a %@"
这也允许你做一些奇怪的事情,比如:

Text("\(car, specifier: "%p")") // shows a pointer to car

(This正在调用this other overload

相关问题