【问题标题】:ios7 font size change when create nsattributedstring from html从html创建nsattributedstring时ios7字体大小发生变化
【发布时间】:2014-01-26 09:27:33
【问题描述】:

我有一个 UITextView,我在其中管理一个 NSAttributedString,最初是通过键盘正常输入的。我将属性字符串保存为 HTML,看起来不错。 当我再次加载它并将其从 HTML 转换回属性字符串时,字体大小似乎发生了变化。

例如,加载时的 HTML 如下所示:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 21.0px Helvetica; color: #000000; -webkit-text-        stroke: #000000}
span.s1 {font-family: 'Helvetica'; font-weight: normal; font-style: normal; font-size:     21.00pt;     font-kerning: none}
</style>
</head>
<body>
<p class="p1"><span class="s1">There is some text as usual lots of text</span></p>
</body>
</html>

我转换它并使用以下代码检查属性:

    // convert to attributed string
    NSError *err;
    NSAttributedString *as = [[NSAttributedString alloc] initWithData:data3
                            options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                      NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
                            documentAttributes:nil
                            error:&err] ;

    NSMutableAttributedString *res = [as mutableCopy];
    [res enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, res.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
        if (value) {
            UIFont *oldFont = (UIFont *)value;
            NSLog(@"On Loading: Font size %f, in range from %d length %d", oldFont.pointSize, range.location, range.length);
        }
    }];

输出显示字体大小从21增加到28:

On Loading: Font size 28.000000, in range from 0 length 40
On Loading: Font size 21.000000, in range from 40 length 1

基本上,每次我加载字符串时,字体大小都会增加。我需要将它存储为 HTML 而不是 NSData,因为它也将被其他平台使用。

有人知道为什么会这样吗?

【问题讨论】:

    标签: html fonts ios7 nsattributedstring


    【解决方案1】:

    我也遇到了这个问题,我通过迭代属性并重置旧字体大小来修复它,如下所示

    NSMutableAttributedString *res = [attributedText mutableCopy];
    [res beginEditing];
    [res enumerateAttribute:NSFontAttributeName
                    inRange:NSMakeRange(0, res.length)
                    options:0
                 usingBlock:^(id value, NSRange range, BOOL *stop) {
                     if (value) {
                         UIFont *oldFont = (UIFont *)value;
                         UIFont *newFont = [oldFont fontWithSize:15];
                         [res addAttribute:NSFontAttributeName value:newFont range:range];
                     }
                 }];
    [res endEditing];
    [self.textFileInputView setAttributedText:res];
    

    【讨论】:

    • 感谢您的回复,至少我不是唯一一个!我希望避免再次设置尺寸,因为这也是我唯一能想到的。
    • 我也有这个问题,正在寻找解决方案,但现在没有找到。如果你有任何请张贴。谢谢
    • 看来只有这个了。使用 fontSize 设置变量并使用它而不是固定大小。为我做的工作!
    • 这很有帮助,谢谢。我也有这个问题。就我而言,上述解决方案会丢失与字体相关的其他属性。我用 UIFont *newfont = [UIFont fontWithDescriptor:[oldFont fontDescriptor] size:size] 克服了这个问题
    • 这方面有更新吗?
    【解决方案2】:

    使用 &lt;span&gt; 和 css 对我有用,遵循 Parsing HTML into NSAttributedText - how to set font?:

    // HTML -> NSAttributedString
    + (NSAttributedString *)attributedStringFromHTML:(NSString *)html {
        NSError *error;
        NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
        NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:&error];
        if(!attrString) {
            NSLog(@"creating attributed string from HTML failed: %@", error.debugDescription);
        }
        return attrString;
    }
    
    // force font thrugh <span> & css
    + (NSAttributedString *)attributedStringFromHTML:(NSString *)html withFont:(UIFont *)font    {
        return [Util attributedStringFromHTML:[NSString stringWithFormat:@"<span style=\"font-family: %@; font-size: %f\";>%@</span>", font.fontName, font.pointSize, html]];
    }
    

    这会设置字体名称和大小,但不会影响样式。

    【讨论】:

      【解决方案3】:

      使用以下代码修复了这种神奇的 Apple 行为:

      static CGFloat const kListsLeading = 10.0;
      static CGFloat const kListsAdditionalShift = 4.0;
      
      //
      // Fix Apple magic 4/3 koefficient
      // http://stackoverflow.com/questions/20992950/ios7-font-size-change-when-create-nsattributedstring-from-html
      //
      static NSAttributedString *DecreaseFontSizeBecauseOfAppleMagic(NSAttributedString *astr) {
          NSMutableAttributedString *mastr = [astr mutableCopy];
      
          [mastr enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, astr.length) options:0 usingBlock:^(UIFont *_Nullable value, NSRange range, BOOL *_Nonnull stop) {
              if (value) {
                  UIFont *font = [value fontWithSize:value.pointSize * 0.75];
                  [mastr addAttribute:NSFontAttributeName value:font range:range];
              }
          }];
      
          [mastr enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, astr.length) options:0 usingBlock:^(NSParagraphStyle *_Nullable value, NSRange range, BOOL *_Nonnull stop) {
              if (value) {
                  NSMutableParagraphStyle *style = [value mutableCopy];
                  style.minimumLineHeight *= 0.75;
                  if (style.firstLineHeadIndent == style.headIndent) {
                      style.firstLineHeadIndent *= 0.75;
                      style.headIndent *= 0.75;
                  }
                  else if (style.firstLineHeadIndent < kListsLeading) {
                      CGFloat shift = (kListsLeading - style.firstLineHeadIndent);
                      style.headIndent += shift + kListsAdditionalShift;
                      style.firstLineHeadIndent = kListsLeading;
                      NSMutableArray *tabs = [NSMutableArray array];
                      NSInteger index = 0;
                      for (NSTextTab *tab in style.tabStops) {
                          [tabs addObject:[[NSTextTab alloc] initWithTextAlignment:tab.alignment location:tab.location + shift + kListsAdditionalShift * (index ? 1 : 0) options:tab.options]];
                          index++;
                      }
                      style.tabStops = tabs;
                  }
                  style.tailIndent *= 0.75;
                  [mastr addAttribute:NSParagraphStyleAttributeName value:style range:range];
              }
          }];
      
          return [mastr copy];
      }
      

      【讨论】:

      • 赞成,因为虽然它是一个可怕的组合,但它是可怕的,因为它是必不可少的(我找不到其他解决方法),而不是因为它的代码 - 干得好!
      • @Grimxn 我刚刚用最新版本的代码更新了我的答案
      【解决方案4】:

      Swift 3.0 版本

      比例为 0.75

      yourAttrStr.beginEditing()
      yourAttrStr.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, yourAttrStr.length), options: .init(rawValue: 0)) { 
              (value, range, stop) in
              if let font = value as? UIFont {
                  let resizedFont = font.withSize(font.pointSize * 0.75)
                  yourAttrStr.addAttribute(NSFontAttributeName, value: resizedFont, range: range)
              }
      }
      yourAttrStr.endEditing()//yourAttrStrwill be the same size as html string
      

      【讨论】:

        【解决方案5】:

        这不完全是一个答案,更多的是一个替代方案和对给出的各种其他答案的评论,所以很抱歉。

        如果您知道字体大小应该是多少,@KishoreThindaak 和 @Danomatika 给出的答案很好 - 但我的应用程序有一个 Mac OS twin 可以生成任何大小的文本,因此必须是通用的。

        @k06a 给出的答案适用于简单文本,但我发现它在嵌入样式时失败 - 特别是在一行上的多个样式本身嵌入在 &lt;li&gt; 标记中。

        经过几个小时的尝试解决这个问题,恐怕我完全放弃了 HTML 作为磁盘格式,转而采用了 RTF,它运行良好,并提供了一个在所有平台上都可读的 RTF 文件。获取以下 RTF 的简单代码...

        extension NSAttributedString {
            func rtf(encoding: String.Encoding) -> Data? {
                let options: [NSAttributedString.DocumentAttributeKey : Any] = [
                    NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtf,
                    NSAttributedString.DocumentAttributeKey.characterEncoding: encoding.rawValue
                ]
                return try? self.data(from: NSMakeRange(0, self.length), documentAttributes: options)
            }
            class func from(rtfData data: Data, encoding: String.Encoding) -> NSAttributedString? {
                let options: [NSAttributedString.DocumentReadingOptionKey : Any] = [
                    NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf,
                    NSAttributedString.DocumentReadingOptionKey.characterEncoding: encoding.rawValue
                ]
                return try? NSMutableAttributedString(data: data, options: options, documentAttributes: nil)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-05
          相关资源
          最近更新 更多