我有一个字符串"Hello {world}"需要替换为"Hello ". 占位符的位置最后并不固定。我可能有不止一个占位符。
我正在使用 SwiftUI 并尝试使其与
Text("Hello {world}".replacingOccurrences(of: "{world}", with: "\(Image(systemName: "globe"))"))
Run Code Online (Sandbox Code Playgroud)
但很快发现这不起作用并提出了这个Hello Image(provider: SwiftUI.ImageProviderBox<SwiftUI.Image.(unknown context at $1ba606db0).NamedImageProvider>)
既然这有效
Text(LocalizedStringKey("Hello \(Image(systemName: "globe"))"))
Run Code Online (Sandbox Code Playgroud)
我认为我需要将 a 传递LocalizedStringKey到Text我再次尝试的
Text(LocalizedStringKey("Hello {world}".replacingOccurrences(of: "{world}", with: "\(Image(systemName: "globe"))")))
Text(LocalizedStringKey("Hello" + "\(Image(systemName: "globe"))")) //this doesn't work either
Run Code Online (Sandbox Code Playgroud)
但遇到了类似的问题SwiftUI.Text.Storage.anyTextStorage(SwiftUI.(unknown context at $1ba668448).LocalizedTextStorage
LocalizedStringKey我查看了和的 API LocalizedStringKey.StringInterpolation,但找不到解决此问题的方法。有没有办法可以替换占位符字符串?
看了 @bewithyou 的答案后,我想到我需要将其拆分为多个子字符串并单独重新组合文本。这是我能想到的最好的解决方案:
public extension String {
func componentsKeepingSeparator(separatedBy separator: Self) -> Array<String> {
self.components(separatedBy: separator)
.flatMap { [$0, separator] }
.dropLast()
.filter { $0 != "" }
}
}
Run Code Online (Sandbox Code Playgroud)
在操场上,如果我运行它,它会完美运行。
PlaygroundPage.current.setLiveView(
"Hello {world}!"
.componentsKeepingSeparator(separatedBy: "{world}")
.reduce(Text("")) { text, str in
if str == "{world}" { return text + Text("\(Image(systemName: "globe"))") }
return text + Text(str)
}
)
Run Code Online (Sandbox Code Playgroud)
我确信有一个更优化的解决方案,但目前就这样。
编辑:
由于我需要支持多个占位符,因此我添加了一些扩展来更全面地完成这项工作。
func componentsKeepingSeparators(separatedBy separators: [Self]) -> [String] {
var finalResult = [self]
separators.forEach { separator in
finalResult = finalResult.flatMap { strElement in
strElement.componentsKeepingSeparator(separatedBy: separator)
}
}
return finalResult
}
Run Code Online (Sandbox Code Playgroud)
以及在操场上
PlaygroundPage.current.setLiveView(
"Hello {world}{world}{world}! {wave}"
.componentsKeepingSeparators(separatedBy: ["{world}", "{wave}"])
.reduce(Text("")) { text, str in
if str == "{world}" { return text + Text("\(Image(systemName: "globe"))") }
if str == "{wave}" { return text + Text("\(Image(systemName: "hand.wave"))") }
return text + Text(str)
}
)
Run Code Online (Sandbox Code Playgroud)
这个扩展有一个双循环,可能不是很有效,所以再次,如果有人能想到更好的解决方案,请发帖。
我通过回答这个问题来提出这个问题,它激起了我的兴趣。正如我在回答中所说,秘密在于LocalizedStringKey,当使用插值字符串文字初始化时,能够构建对 SwiftUIImage类型的引用,这些类型可以在Text.
因为您没有使用插值字符串文字,所以您可以通过多个 来构建内容Texts,如此处的其他答案所示,或者使用 做一些聪明的事情LocalizedStringKey.StringInterpolation。LocalizedStringKey这种方法的优点是,您还可以在任何其他使用的视图(几乎是任何显示文本的视图)中使用图像保存文本。
此扩展LocalizedStringKey将手动构建一个内插字符串:
extension LocalizedStringKey {
private static let imageMap: [String: String] = [
"world": "globe",
"moon": "moon"
]
init(imageText: String) {
var components = [Any]()
var length = 0
let scanner = Scanner(string: imageText)
scanner.charactersToBeSkipped = nil
while scanner.isAtEnd == false {
let up = scanner.scanUpToString("{")
let start = scanner.scanString("{")
let name = scanner.scanUpToString("}")
let end = scanner.scanString("}")
if let up = up {
components.append(up)
length += up.count
}
if let name = name {
if start != nil, end != nil, let imageName = Self.imageMap[name] {
components.append(Image(systemName: imageName))
length += 1
} else {
components.append(name)
}
}
}
var interp = LocalizedStringKey.StringInterpolation(literalCapacity: length, interpolationCount: components.count)
for component in components {
if let string = component as? String {
interp.appendInterpolation(string)
}
if let image = component as? Image {
interp.appendInterpolation(image)
}
}
self.init(stringInterpolation: interp)
}
}
Run Code Online (Sandbox Code Playgroud)
如果这些值来自 API,您可能想要缓存它们,我尚未在渲染循环中检查此代码的性能。
Text您可以在或任何其他视图上添加扩展:
extension Text {
init(imageText: String) {
self.init(LocalizedStringKey(imageText: imageText))
}
}
Run Code Online (Sandbox Code Playgroud)
所以你可以这样做:
Text(imageText: "Hello {world}! or {moon} or {unmapped}")
Run Code Online (Sandbox Code Playgroud)
这给你:
| 归档时间: |
|
| 查看次数: |
825 次 |
| 最近记录: |