Примените полужирный шрифт к части NSAttributedString, сохранив при этом размеры шрифта и начертания.

Я работаю над текстовым редактором для iOS, используя UITextView вместе с NSAttributedString. Он будет работать аналогично традиционным (т. е. выбрать область, нажать кнопку и применить этот эффект к этой области, сохраняя при этом любые другие атрибуты текста.

К сожалению с NSAttributedString не все из них можно настроить самостоятельно. Некоторые из них (по крайней мере, жирный шрифт, шрифт и размер шрифта) требуют передачи UIFont, который установит все эти атрибуты для региона (даже если вы хотите установить только один). Учитывая, что одна область может включать несколько граней и размеров, это приведет к тому, что наивный подход нарушит большую часть существующего форматирования.

Есть ли рекомендуемые средства для этого? Я думаю, что мой единственный вариант будет состоять в том, чтобы перебирать атрибуты для региона, к которому я хочу применить его, группировать его в фрагменты, которые имеют те же другие атрибуты шрифта, а затем применять его к каждому фрагменту по отдельности.


person Kitsune    schedule 04.01.2013    source источник


Ответы (2)


У вас есть правильная идея, и алгоритм уже предоставлен вам enumerateAttribute:inRange:options:usingBlock:. Чтобы использовать это для обработки шрифтов:

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

где addBoldBlock берет текущий шрифт (предоставленный в качестве первого аргумента блока), добавляет полужирный шрифт и применяет его к текущему фрагменту (предоставляется в качестве второго аргумента блока).

person CRD    schedule 04.01.2013

Это то, что я использую в своем 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];
}

При этом используется DTCoreTextFontDescriptor из проекта DTCoreText с открытым исходным кодом.

PS: вам нужно будет соответствующим образом настроить его для использования с UIFont.

person Cocoanetics    schedule 05.01.2013