我有一个字符串--让我们说“我的名字是%@,我在类%@中学习”--现在我想用粗体显示将要插入的占位符文本,这样结果会类似这样:“我的名字是,我学习在10类中”,我将在标签上显示它
我已经尝试过使用NSAttributedString,但是由于字符串将被本地化,所以我无法使用属性化字符串的范围参数来使其粗体。
发布于 2022-02-22 08:31:39
let withFormat = "my name is %@ and i study in class %@"
这样做有不同的方法,但在我看来,最简单的方法之一是使用标记:
使用占位符周围的标记(如果需要的话使用其他部分):
let withFormat = "my name is <b>%@</b> and i study in class <b>%@</b>"
let withFormat = "my name is [b]%@[/b] and i study in class [b]%@[/b]"
let withFormat = "my name is **%@** and i study in class **%@**"
标记可以是HTML、Markdown、BBCode或任何您想要的自定义,然后,替换占位符值:
let localized = String(format: withFormat, value1, value2)
现在,根据您想要这样做的方式或者您使用的标记,您可以使用来自HTML、Markdown等的NSAttributedString
的init,或者简单地使用NSAttributedString(string: localized)
,查找标记并应用所需的呈现效果。
下面是一个小小的例子:
let tv = UITextView(frame: CGRect(x: 0, y: 0, width: 300, height: 130))
tv.backgroundColor = .orange
let attributedString = NSMutableAttributedString()
let htmled = String(format: "my name is <b>%@</b> and i study in class <b>%@</b>", arguments: ["Alice", "Wonderlands"])
let markdowned = String(format: "my name is **%@** and i study in class **%@**", arguments: ["Alice", "Wonderlands"])
let bbcoded = String(format: "my name is [b]%@[/b] and i study in class [b]%@[/b]", arguments: ["Alice", "Wonderlands"])
let separator = NSAttributedString(string: "\n\n")
let html = try! NSAttributedString(data: Data(htmled.utf8), options: [.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil)
attributedString.append(html)
attributedString.append(separator)
let markdown = try! NSAttributedString(markdown: markdowned, baseURL: nil) //iO15+
attributedString.append(markdown)
attributedString.append(separator)
let bbcode = NSMutableAttributedString(string: bbcoded)
let regex = try! NSRegularExpression(pattern: "\\[b\\](.*?)\\[\\/b\\]", options: [])
let matches = regex.matches(in: bbcode.string, options: [], range: NSRange(location: 0, length: bbcode.length))
let boldEffect: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 12)]
//We use reversed() because if you replace the first one, you'll remove [b] and [/b], meaning that the other ranges will be affected, so the trick is to start from the end
matches.reversed().forEach { aMatch in
let valueRange = aMatch.range(at: 1) //We use the regex group
let replacement = NSAttributedString(string: bbcode.attributedSubstring(from: valueRange).string, attributes: boldEffect)
bbcode.replaceCharacters(in: aMatch.range, with: replacement)
}
attributedString.append(bbcode)
tv.attributedText = attributedString
输出:
发布于 2022-02-22 07:09:26
我可以使用NSRegularExpression
提供一个简单的解决方案,而不需要任何复杂/可怕的正则表达式。我相信有比这更好的解决办法。
这些步骤非常接近于上面提到的重要意义。
在数组中存储要注入的字符串( has,13)等等,该字符串具有placeholders
locations array
NSMutableAttributedString
,通过字符串注入数组并更新NSMutableAttributedString
的区域。下面是我用一些注释来解释的代码:
// This is not needed, just part of my UI
// Only the inject part is relevant to you
@objc
private func didTapSubmitButton()
{
if let inputText = textField.text
{
let input = inputText.components(separatedBy: ",")
let text = "My name is %@ and I am %@ years old"
inject(input, into: text)
}
}
// The actual function
private func inject(_ strings: [String],
into text: String)
{
let placeholderString = "%@"
// Store all the positions of the %@ in the string
var placeholderIndexes: [Int] = []
// Locate the %@ in the original text
do
{
let regex = try NSRegularExpression(pattern: placeholderString,
options: .caseInsensitive)
// Loop through all the %@ found and store their locations
for match in regex.matches(in: text,
options: NSRegularExpression.MatchingOptions(),
range: NSRange(location: 0,
length: text.count))
as [NSTextCheckingResult]
{
// Append your placeholder array with the location
placeholderIndexes.append(match.range.location)
}
}
catch
{
// handle errors
print("error")
}
// Expand your string by inserting the parameters
let updatedText = String(format: text, arguments: strings)
// Configure an NSMutableAttributedString with the updated text
let attributedText = NSMutableAttributedString(string: updatedText)
// Keep track of an offset
// Initially when you store the locations of the %@ in the text
// My name is %@ and my age is %@ years old, the location is 11 and 27
// But when you add Harsh, the next location should be increased by
// the difference in length between the placeholder and the previous
// string to get the right location of the second parameter
var offset = 0
// Loop through the strings you want to insert
for (index, parameter) in strings.enumerated()
{
// Get the corresponding location of where it was inserted
// Plus the offset as discussed above
let locationOfString = placeholderIndexes[index] + offset
// Get the length of the string
let stringLength = parameter.count
// Create a range
let range = NSRange(location: locationOfString,
length: stringLength)
// Set the bold font
let boldFont
= UIFont.boldSystemFont(ofSize: displayLabel.font.pointSize)
// Set the attributes for the given range
attributedText.addAttribute(NSAttributedString.Key.font,
value: boldFont,
range: range)
// Update the offset as discussed above
offset = stringLength - placeholderString.count
}
// Do what you want with the string
displayLabel.attributedText = attributedText
}
最终结果:
局部字符串参数化字符串粗体部分粗体Swift NSAttributedString iOS
这应该足够灵活,可以处理字符串中存在的任意数量的占位符,并且不需要跟踪不同的占位符。
发布于 2022-02-22 07:11:18
let descriptionString = String(format: "localised_key".localized(), Harsh, 10)
let description = NSMutableAttributedString(string: descriptionString, attributes: [NSAttributedString.Key.font: UIFont(name: "NotoSans-Regular", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5])
let rangeName = descriptionString.range(of: "Harsh")
let rangeClass = descriptionString.range(of: "10")
let nsrangeName = NSRange(rangeName!, in: descriptionString)
let nsrangeClass = NSRange(rangeClass!, in: descriptionString)
description.addAttributes([NSAttributedString.Key.font: UIFont(name: "NotoSans-Bold", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5], range: nsrangeName)
description.addAttributes([NSAttributedString.Key.font: UIFont(name: "NotoSans-Bold", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5], range: nsrangeClass)
有关更多参考资料,请使用this
https://stackoverflow.com/questions/71216333
复制相似问题