首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使局部字符串粗体快速

使局部字符串粗体快速
EN

Stack Overflow用户
提问于 2022-02-22 05:29:50
回答 3查看 1.3K关注 0票数 3

我有一个字符串--让我们说“我的名字是%@,我在类%@中学习”--现在我想用粗体显示将要插入的占位符文本,这样结果会类似这样:“我的名字是,我学习在10类中”,我将在标签上显示它

我已经尝试过使用NSAttributedString,但是由于字符串将被本地化,所以我无法使用属性化字符串的范围参数来使其粗体。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-02-22 08:31:39

代码语言:javascript
运行
复制
let withFormat = "my name is %@ and i study in class %@"

这样做有不同的方法,但在我看来,最简单的方法之一是使用标记:

使用占位符周围的标记(如果需要的话使用其他部分):

代码语言:javascript
运行
复制
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或任何您想要的自定义,然后,替换占位符值:

代码语言:javascript
运行
复制
let localized = String(format: withFormat, value1, value2)

现在,根据您想要这样做的方式或者您使用的标记,您可以使用来自HTML、Markdown等的NSAttributedString的init,或者简单地使用NSAttributedString(string: localized),查找标记并应用所需的呈现效果。

下面是一个小小的例子:

代码语言:javascript
运行
复制
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

输出:

票数 3
EN

Stack Overflow用户

发布于 2022-02-22 07:09:26

我可以使用NSRegularExpression提供一个简单的解决方案,而不需要任何复杂/可怕的正则表达式。我相信有比这更好的解决办法。

这些步骤非常接近于上面提到的重要意义。

在数组中存储要注入的字符串( has,13)等等,该字符串具有placeholders

  • Use REGEX以查找占位符的位置,并将这些位置存储在locations array

  • Update中,方法是用字符串数组

  • 的值替换占位符,通过字符串创建一个NSMutableAttributedString,通过字符串注入数组并更新NSMutableAttributedString的区域。

下面是我用一些注释来解释的代码:

代码语言:javascript
运行
复制
// 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

这应该足够灵活,可以处理字符串中存在的任意数量的占位符,并且不需要跟踪不同的占位符。

票数 0
EN

Stack Overflow用户

发布于 2022-02-22 07:11:18

代码语言:javascript
运行
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71216333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档