Apply bolding to portion of NSAttributedString, while preserving font sizes and faces

 ̄綄美尐妖づ 提交于 2019-12-08 01:09:03

问题


I'm working on a rich text editor for iOS, using a UITextView along with an NSAttributedString. It'll function similarly to traditional ones (i.e. selecting a region, clicking a button, and it applies that effect to that region, while preserving any other attributes on the text.

Unfortunately with NSAttributedString, not all of them can be adjusted independently. Several of them (at least bold, font face, and font size) all require passing a UIFont, which'll set all of those attributes for the region (even if you only wanted to set one). Seeing as a single region might include several faces and sizes, this'll result in the naive approach breaking a lot of existing formatting.

Is there any recommended means to accomplish this? I'm thinking my only option will be to iterate through the attributes for the region I want to apply it to, group it into chunks that have the same other font attributes, and then apply it to each chunk individually.


回答1:


You have the right idea and the algorithm is already provided for you by enumerateAttribute:inRange:options:usingBlock:. To use this to process font runs:

[myAttributedString enumerateAttribute:NSFontAttributeName
                               inRange:selectedRange
                               options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                            usingBlock:addBoldBlock
]

where addBoldBlock takes the current font (supplied as first argument to the block), adds bold, and applies it to the current chunk (supplied as second argument to the block).




回答2:


This is what I use in my DTRichTextEditor:

- (void)toggleBoldInRange:(NSRange)range
{
    // first character determines current boldness
    NSDictionary *currentAttributes = [self typingAttributesForRange:range];

    if (!currentAttributes)
    {
        return;
    }

    [self beginEditing];

    CTFontRef currentFont = (__bridge CTFontRef)[currentAttributes objectForKey:(id)kCTFontAttributeName];
    DTCoreTextFontDescriptor *typingFontDescriptor = [DTCoreTextFontDescriptor fontDescriptorForCTFont:currentFont];

    // need to replace name with family
    CFStringRef family = CTFontCopyFamilyName(currentFont);
    typingFontDescriptor.fontFamily = (__bridge NSString *)family;
    CFRelease(family);

    typingFontDescriptor.fontName = nil;

    NSRange attrRange;
    NSUInteger index=range.location;

    while (index < NSMaxRange(range)) 
    {
        NSMutableDictionary *attrs = [[self attributesAtIndex:index effectiveRange:&attrRange] mutableCopy];
        CTFontRef currentFont = (__bridge CTFontRef)[attrs objectForKey:(id)kCTFontAttributeName];

        if (currentFont)
        {
            DTCoreTextFontDescriptor *desc = [DTCoreTextFontDescriptor fontDescriptorForCTFont:currentFont];

            // need to replace name with family
            CFStringRef family = CTFontCopyFamilyName(currentFont);
            desc.fontFamily = (__bridge NSString *)family;
            CFRelease(family);

            desc.fontName = nil;

            desc.boldTrait = !typingFontDescriptor.boldTrait;
            CTFontRef newFont = [desc newMatchingFont];
            [attrs setObject:(__bridge id)newFont forKey:(id)kCTFontAttributeName];
            CFRelease(newFont);

            if (attrRange.location < range.location)
            {
                attrRange.length -= (range.location - attrRange.location);
                attrRange.location = range.location;
            }

            if (NSMaxRange(attrRange)>NSMaxRange(range))
            {
                attrRange.length = NSMaxRange(range) - attrRange.location;
            }

            [self setAttributes:attrs range:attrRange];
        }

        index += attrRange.length;
    }

    [self endEditing];
}

This uses DTCoreTextFontDescriptor from the open source DTCoreText project.

PS: You'd have to adjust it for use with UIFont accordingly.



来源:https://stackoverflow.com/questions/14161254/apply-bolding-to-portion-of-nsattributedstring-while-preserving-font-sizes-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!