在 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 应该不难(因为您似乎已经知道一些方法)。
attr1
用 init(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
是两个UITextView
(IBOulet
)。
它呈现:(_tv1
是最上面的一个,_tv2
是第二个)。
我有一些纯 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 应该不难(因为您似乎已经知道一些方法)。
attr1
用 init(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
是两个UITextView
(IBOulet
)。
它呈现:(_tv1
是最上面的一个,_tv2
是第二个)。