将嵌套的粗体斜体HTML标记转换为NSAttributedString

时间:2015-09-02 13:10:34

标签: html ios objective-c attributes nsattributedstring

我使用此代码使用RegEx将HTML字符串转换为NSAttributedString。我唯一的问题是嵌套的粗体和斜体标签。 RegEx是正确的方法吗?

另外,我想避免使用HTML解析器,因为我需要的只有Bold,Italic和Underline属性以及StrikeThrough(如果可能)。

有什么建议吗?

- (NSMutableAttributedString *)applyStylesToString:(NSString *)string searchRange:(NSRange)searchRange {

    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
    [attributedString addAttribute:NSFontAttributeName value:[StylesConfig regularLargeFont] range:searchRange];

    NSDictionary *boldAttributes = @{ NSFontAttributeName : [StylesConfig regularBoldLargeFont] };
    NSDictionary *italicAttributes = @{ NSFontAttributeName : [StylesConfig regularItalicLargeFont] };
    NSDictionary *underlineAttributes = @{ NSUnderlineStyleAttributeName : @1};
    NSDictionary *strikeThroughAttributes = @{ NSStrikethroughStyleAttributeName : @1};

    NSDictionary *replacements = @{
                                   @"<b>(.*?)</b>" : boldAttributes,
                                   @"<i>(.*?)</i>" : italicAttributes,
                                   @"<u>(.*?)</u>" : underlineAttributes,
                                   @"<s>(.*?)</s>" : strikeThroughAttributes
                                   };

    for (NSString *key in replacements) {

        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:key options:0 error:nil];

        [regex enumerateMatchesInString:string options:0 range:searchRange usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
            NSRange matchRange = [match rangeAtIndex:1];

            [attributedString addAttributes:replacements[key] range:matchRange];

            if ([key isEqualToString:@"<b>(.*?)</b>"]) {
                [self makeBoldItalic:attributedString matchRange:matchRange font:@"SourceSansPro-It"];

            } else if ([key isEqualToString:@"<i>(.*?)</i>"]) {
                [self makeBoldItalic:attributedString matchRange:matchRange font:@"SourceSansPro-Semibold"];
            }
        }];
    }
    [[attributedString mutableString] replaceOccurrencesOfString:@"<b>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"</b>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"<i>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"</i>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"<u>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"</u>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"<s>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];
    [[attributedString mutableString] replaceOccurrencesOfString:@"</s>" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, attributedString.length)];

    return attributedString;
}

- (void)makeBoldItalic:(NSMutableAttributedString *)attributedString matchRange:(NSRange)matchRange font:(NSString *)font {

    [attributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {

        UIFont *oldFont = (UIFont *)value;
        if ([oldFont.fontName isEqualToString:font]) {

            [attributedString removeAttribute:NSFontAttributeName range:range];
            NSDictionary *boldItalicAttributes = @{ NSFontAttributeName : [StylesConfig regularBoldItalicLargeFont] };
            [attributedString addAttributes:boldItalicAttributes range:matchRange];
        }
    }];
}

1 个答案:

答案 0 :(得分:5)

事实是Bold和Italic(以及其他属性)是字体的一部分,与下划线不同。 iOS并没有给出一个假的粗体&#34;或者&#34;伪造斜体&#34;就像Photoshop可以做的那样。

所以,我猜您从boldFont类实用程序中得到了: italicFontboldItalicFontboldFont = [StylesConfig regularBoldLargeFont]; //SourceSansPro-Semibold italicFont = [StylesConfig regularItalicLargeFont];//SourceSansPro-It boldItalicFont = [StylesConfig regularBoldItalicLargeFont];//SourceSansPro-SemiboldIt (or something like this)

symbolicTraits

因此,要更改字体,期望其fontDescriptor -(void)boldText:(NSMutableAttributedText *)attributeString forRange:(NSRange)range { [attributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) { UIFont *currentFont = (UIFont *)value; if ([[currentFont fontDescriptor] symbolicTraits] & UIFontDescriptorTraitBold) { NSLog(@"Font is already bold); } else { UIFont *newFont = [self boldFontFromFont:currentFont]; [attributedString addAttribute:newFont range:range]; } }]; } -(void)italicText:(NSMutableAttributedText *)attributeString forRange:(NSRange)range { [attributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) { UIFont *currentFont = (UIFont *)value; if ([[currentFont fontDescriptor] symbolicTraits] & UIFontDescriptorTraitItalic) { NSLog(@"Font is already italic); } else { UIFont *newFont = [self italicFontFromFont:currentFont]; [attributedString addAttribute:newFont range:range]; } }]; } -(UIFont *)boldFontFromFont:(UIFont *)font { if ([[currentFont fontDescriptor] symbolicTraits] & UIFontDescriptorTraitItalic) return boldItalicFont; else return boldFont; } -(UIFont *)italicFontFromFont:(UIFont *)font { if ([[currentFont fontDescriptor] symbolicTraits] & UIFontDescriptorTraitBold) return boldItalicFont; else return italicFont; } 中的字体包含正确的字体,您可以执行以下操作:

if ([key isEqualToString:@"<b>(.*?)</b>"]) 
{
    [self boldText: attributedString forRange:matchRange];
}
 else if ([key isEqualToString:@"<i>(.*?)</i>"]) 
{
    [self italicText: attributedString forRange:matchRange];
}

在您当前的代码中:

symbolicTraits

如果您的字体未通过UIFont测试,则可能需要查看fontName fast并检查其字体是否为粗体,斜体或粗体。

注意:
我没有测试代码,我只在这里写,我甚至不知道它是否编译,但那应该给你全部的想法。