【问题标题】:Apply bolding to portion of NSAttributedString, while preserving font sizes and faces对部分 NSAttributedString 应用粗体,同时保留字体大小和面
【发布时间】:2013-01-04 16:47:57
【问题描述】:

我正在开发适用于 iOS 的富文本编辑器,使用 UITextViewNSAttributedString。它的功能类似于传统的(即选择一个区域,单击一个按钮,并将该效果应用于该区域,同时保留文本上的任何其他属性。

不幸的是NSAttributedString,并不是所有的都可以独立调整。其中一些(至少是粗体、字体和字体大小)都需要传递一个UIFont,它将为该区域设置所有这些属性(即使您只想设置一个)。将单个区域视为可能包含多个面和大小,这将导致幼稚的方法破坏许多现有格式。

有没有推荐的方法来完成这个?我认为我唯一的选择是遍历我想要应用它的区域的属性,将其分组为具有相同其他字体属性的块,然后将其分别应用于每个块。

【问题讨论】:

    标签: objective-c ios nsattributedstring


    【解决方案1】:

    你的想法是对的,enumerateAttribute:inRange:options:usingBlock: 已经为你提供了算法。要使用它来处理字体运行:

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

    其中 addBoldBlock 采用当前字体(作为块的第一个参数提供),添加粗体,并将其应用于当前块(作为块的第二个参数提供)。

    【讨论】:

      【解决方案2】:

      这是我在 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];
      }
      

      这使用来自开源 DTCoreText 项目的 DTCoreTextFontDescriptor。

      PS:您必须相应地调整它以与 UIFont 一起使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-19
        • 1970-01-01
        相关资源
        最近更新 更多