在 Swift 中使用 NSRegularExpression 对特定范围内的词进行属性化

Attribute the word within a specific range using NSRegularExpression in Swift

我有一些纯 Html 字符串,其中一些有标题标签 <b>Title</b>

facilities: "<b>Facilities</b><br/>24-hour security, Barbecue area, Car park, Clubhouse, Function room, Gym, Outdoor swimming pool, Playground, Swimming pool<br/><br/><b>Rooms</b><br/>Dining room, Ensuites, Living room, Maid\'s room, Utility room<br/><br/><b>Outdoor</b><br/>Balcony<br/><br/><b>View</b><br/>City, Open<br/><br/><b>Direction</b><br/>South East"

所以我使用 NSRegularExpression 模式从字符串中提取标题并存储在字符串数组中。后来,我将这些标题设为粗体(属性字符串)并显示。所以我就是这样做的:

var titlesArray = [String]()
let regex = try! NSRegularExpression(pattern: "<b>(.*?)</b>", options: [])
let basicDescription = facilities as NSString

regex.enumerateMatchesInString(facilities, options: [], range: NSMakeRange(0, facilities.characters.count)) { result, flags, stop in
  if let range = result?.rangeAtIndex(1) {
    titlesArray.append(basicDescription.substringWithRange(range))
  }
}

let convertedDescription = facilities.html2String as NSString
let attributedString = NSMutableAttributedString(string: convertedDescription as String, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(14.0)])
let boldFontAttribute = [NSFontAttributeName: UIFont.boldSystemFontOfSize(15.0)]

if titlesArray.count > 0 {
   for i in 0..<titlesArray.count {
   attributedString.addAttributes(boldFontAttribute, range: convertedDescription.rangeOfString(titlesArray[i]))
   } 
}

所以,一切都很好。但问题是,有时我收到 Html 标记的字符串,其中有重复的单词,其中一个是带有标题标签的标题,另一个只是一个简单的单词,我不需要加粗。但是此函数将查找该词并在 for 循环中将其加粗,并忽略简单词后的真实标题。

这是我得到的:

所以在这里,我怎么能忽略第一个 "Outdoor" 并加粗我想要的第二个。感谢您的帮助。

我不知道你到底想做什么,但你考虑过使用 initializer that takes HTML?

Playgrounds 的示例代码为:

if let url = Bundle.main.url(forResource: "file", withExtension: "html") {
    do {
        let data = try Data(contentsOf: url)
        let attributedString = try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
        let labelRect = CGRect(x: 0, y: 0, width: 500, height: 250)
        let label = UILabel(frame: labelRect)
        label.numberOfLines = 2
        label.attributedText = attributedString

    } catch {
        print(error.localizedDescription)
    }
}

有了这个HTML:

<style>
    body {
     font-size: 20;
     font-family: sans-serif;
    }
</style>

<p><b>Hello</b> world</p>
<p>Good morning!</p>

输出如下:

在 Objective-C 中翻译成 Swift 应该不难(因为您似乎已经知道一些方法)。

attr1init(data:, options:, documentAttributes:) 渲染。我没有添加任何其他效果(比如 bold/normal 的首选尺寸、颜色,您只需枚举它并更改效果) attr2 使用正则表达式以您想要的方式呈现。它只是不考虑所有标签,只考虑粗体,而且我几乎没有编写新行的替换代码(<br/>\n)。但这可能是有用的。我没有对您的正则表达式进行更多测试(while 循环可能会卡住?)

NSString *str = @"<b>Facilities</b><br/>24-hour security, Barbecue area, Car park, Clubhouse, Function room, Gym, Outdoor swimming pool, Playground, Swimming pool<br/><br/><b>Rooms</b><br/>Dining room, Ensuites, Living room, Maid\'s room, Utility room<br/><br/><b>Outdoor</b><br/>Balcony<br/><br/><b>View</b><br/>City, Open<br/><br/><b>Direction</b><br/>South East";

NSError *errorAttr1 = nil;
NSAttributedString *attr1 = [[NSAttributedString alloc] initWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType} documentAttributes:nil error:&errorAttr1];
if (errorAttr1)
{
    NSLog(@"Error AttributedStr Conversion with initWithData:options:documentsAttributes:error: %@", errorAttr1);
}
else
{
    NSLog(@"attr1: %@", attr1);
    [_tv1 setAttributedText:attr1];

}

str = [str stringByReplacingOccurrencesOfString:@"<br/>" withString:@"\n"];

NSError *errorRegex = nil;
NSString *openingTag = @"<b>";
NSString *closingTag = @"</b>";
NSString *pattern = [NSString stringWithFormat:@"%@(.*?)%@", openingTag, closingTag];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&errorRegex];
if (errorRegex)
{
    NSLog(@"Error regex: %@", errorRegex);
    return;
}


NSDictionary *boldAttributes = @{NSForegroundColorAttributeName:[UIColor darkGrayColor],
                                 NSFontAttributeName:[UIFont boldSystemFontOfSize:15]};
NSDictionary *normalAttributes = @{NSForegroundColorAttributeName:[UIColor darkGrayColor],
                                   NSFontAttributeName:[UIFont systemFontOfSize:14]};

NSMutableAttributedString *attr2 = [[NSMutableAttributedString alloc] initWithString:str attributes:normalAttributes]; //Add the initial attributes there

//Now we'll add the specific attribues
NSTextCheckingResult *match = [regex firstMatchInString:[attr2 string] options:0 range:NSMakeRange(0, [attr2 length])];
while (match)
{
    NSRange range = [match range];
    NSString *foundStr = [[attr2 string] substringWithRange:range];
    NSAttributedString *temp = [[NSAttributedString alloc] initWithString:[foundStr substringWithRange:NSMakeRange([openingTag length], [foundStr length]-[openingTag length]-[closingTag length])] attributes:boldAttributes];
    [attr2 replaceCharactersInRange:range withAttributedString:temp];
    match = [regex firstMatchInString:[attr2 string] options:0 range:NSMakeRange(0, [attr2 length])];
}
NSLog(@"attr2: %@", attr2);
[_tv2 setAttributedText:attr2];

_tv1_tv2是两个UITextViewIBOulet)。 它呈现:(_tv1 是最上面的一个,_tv2 是第二个)。