【问题标题】:Attributed string with custom fonts in storyboard does not load correctly情节提要中具有自定义字体的属性字符串无法正确加载
【发布时间】:2014-11-13 13:49:29
【问题描述】:

我们在项目中使用自定义字体。它在 Xcode 5 中运行良好。在 Xcode 6 中,它以纯文本、代码中的属性字符串运行。但是那些在 storyboard 中设置的属性字符串在模拟器或设备上运行时都会恢复为 Helvetica,尽管它们在 storyboard 中看起来还不错。

不知道是 Xcode 6 还是 iOS 8 SDK 的 bug,还是 Xcode 6 / iOS 8 改变了自定义字体的使用方式?

【问题讨论】:

  • 这里有同样的问题。很想知道发生了什么。
  • 目前,我们创建了一个自定义 UILabel,命名为 GLMarkdownLabel,并使用 IBInspectable 导出了一些属性,然后在 storyboard 中设置 markdown 字符串,并在从 nib 唤醒时将 markdown 字符串转换回属性字符串。
  • 这是一个长期的解决方案,希望苹果能在下一个 Xcode 版本中修复这个错误。
  • 哎呀,太笨了。感谢您让我们知道这不是一个孤立的问题。有雷达吗?
  • 我们的解决方法最终还是回到使用IBCustomFonts 作为我们的属性标签。

标签: ios swift ios8 xcode6 nsattributedstring


【解决方案1】:

最简单的解决方法是将字体拖到 FontBook 中。如果字体在您的项目中但不在您计算机的 FontBook 中,IB 有时很难找到它。很奇怪,但曾多次为我工作过。

【讨论】:

  • 虽然这会让 Xcode 选择自定义字体,但它实际上不起作用。在运行时,字体不会像您期望的那样使用。
  • 不幸的是,我无法想出一个解决方法。我能做的最好的事情就是向 Apple 记录一个错误。
  • 是的,这就是修复。我的故事板是由另一个开发人员设计的,svn update ok,但从未在 UI 中获得字体。字体在资源中,但未显示在设备/模拟器 UI 中。由于他使用属性字符串,我必须在字体书中有它。这样就解决了问题。
  • 是的。这有助于我解决同样的问题。当我将自定义字体添加到字体书中时,事情就像魅力一样。
  • 虽然此解决方案适用于某些情况,但我也遇到了与 @Daniel 在同一项目中使用相同字体系列的相同问题。 XCode 需要解决这个问题。
【解决方案2】:

对我来说,解决方法是使用 IBDesignable 类:

import UIKit

@IBDesignable class TIFAttributedLabel: UILabel {

    @IBInspectable var fontSize: CGFloat = 13.0

    @IBInspectable var fontFamily: String = "DIN Light"

    override func awakeFromNib() {
        var attrString = NSMutableAttributedString(attributedString: self.attributedText)
        attrString.addAttribute(NSFontAttributeName, value: UIFont(name: self.fontFamily, size: self.fontSize)!, range: NSMakeRange(0, attrString.length))
        self.attributedText = attrString
    }
}

在 Interface Builder 中为您提供:

您可以像往常一样设置您的属性字符串,但您必须在新的可用属性中再次设置您的 fontsize 和 fontfamily。

由于 Interface Builder 默认使用自定义字体,这会导致 所见即所得,这是我在构建应用程序时更喜欢的。

注意

我使用它而不是普通版本的原因是我在属性标签上设置属性,如行间距,使用普通样式时不可用。

【讨论】:

  • 您的解决方案只支持一种字体系列和标签大小,那么为什么不直接使用纯文本呢?
  • 同样,我们暂时使用@IBInspectable 属性,而不是字体和大小。我们有一个markdownText 属性,因为大多数时候,我们将属性字符串用于粗体或带下划线的文本。然后将降价文本解析为属性字符串,并为纯文本设置字体和大小信息。
  • @AllenHsu,你是对的。没有提到这一点,但我正在为我的标签使用属性行间距。当然,否则您将只使用简单的样式:)
  • 好点,我们也导出了 lineSpacing :p 我想我会接受你的回答,因为它实际上是 Xcode 中的一个错误,目前没有更好的解决方案。让我们等待 Xcode 的下一个版本。
  • 如果我想将部分文本加粗,这将不起作用
【解决方案3】:

您可以将自定义字体添加到字体册。

Step1:点击管理字体。它打开字体册。

第二步:点击加号并添加您的字体。

下次当您单击带有属性文本的字体时,新添加的字体也将显示在列表中。 但请确保您的自定义字体已添加到 info.plist 和捆绑资源中。

【讨论】:

  • 这在情节提要中确实有效,但运行后不显示格式
  • @Van 格式?你能告诉我更多吗?什么时候不工作?
  • 我必须设置 rgualr 和粗体混合匹配的文本。我使用了上面的解决方案,所以它在故事板中工作,但是当我运行应用程序时,标签没有显示应用的字体,而是显示系统字体
  • 您是否在 info.plist 中添加了自定义字体?之后只需打印所有字体系列
  • 是的。如果是纯文本,我可以在整个应用程序中设置自定义字体,我需要为属性文本设置
【解决方案4】:

感谢这个帖子,我找到了这个解决方案:

private let fontMapping = [
    "HelveticaNeue-Medium": "ITCAvantGardePro-Md",
    "HelveticaNeue": "ITCAvantGardePro-Bk",
    "HelveticaNeue-Bold": "ITCAvantGardePro-Demi",
]

func switchFontFamily(string: NSAttributedString) -> NSAttributedString {
    var result = NSMutableAttributedString(attributedString: string)
    string.enumerateAttribute(NSFontAttributeName, inRange: NSRange(location: 0, length: string.length), options: nil) { (font, range, _) in
        if let font = font as? UIFont {
            result.removeAttribute(NSFontAttributeName, range: range)
            result.addAttribute(NSFontAttributeName, value: UIFont(name: fontMapping[font.fontName]!, size: font.pointSize)!, range: range)
        }
    }
    return result
}

【讨论】:

  • 好主意。真是难以置信,这在Apple中被打破了。令人惊讶。
【解决方案5】:

我的解决方案有点变通。真正的解决方案是让苹果修复 Interface Builder。

使用它,您可以使用系统字体在界面生成器中标记所有粗体和斜体文本,然后在运行时呈现您的自定义字体。可能并非在所有情况下都是最佳的。

 NSMutableAttributedString* ApplyCustomFont(NSAttributedString *attributedText,
                     UIFont* boldFont,
                     UIFont* italicFont,
                     UIFont* boldItalicFont,
                     UIFont* regularFont)
{

    NSMutableAttributedString *attrib = [[NSMutableAttributedString alloc] initWithAttributedString:attributedText];
    [attrib beginEditing];
    [attrib enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attrib.length) options:0
                    usingBlock:^(id value, NSRange range, BOOL *stop)
    {
        if (value)
        {
            UIFont *oldFont = (UIFont *)value;
            NSLog(@"%@",oldFont.fontName);

            [attrib removeAttribute:NSFontAttributeName range:range];

            if([oldFont.fontName rangeOfString:@"BoldItalic"].location != NSNotFound && boldItalicFont != nil)
                [attrib addAttribute:NSFontAttributeName value:boldItalicFont range:range];
            else if([oldFont.fontName rangeOfString:@"Italic"].location != NSNotFound && italicFont != nil)
                [attrib addAttribute:NSFontAttributeName value:italicFont range:range];
            else if([oldFont.fontName rangeOfString:@"Bold"].location != NSNotFound && boldFont != nil)
                [attrib addAttribute:NSFontAttributeName value:boldFont range:range];
            else if(regularFont != nil)
                [attrib addAttribute:NSFontAttributeName value:regularFont range:range];
        }
    }];
    [attrib endEditing];

    return attrib;
}

灵感来自this post

【讨论】:

    【解决方案6】:

    我一直在努力解决这个错误:UILabel 使用自定义字体在 IB 中正确显示,但在设备或模拟器上无法正确显示(字体包含在项目中,并在普通 UILabel 中使用)。

    终于在 (Mac) App Store 上找到了 Attributed String Creator。生成要放置在应用程序中适当位置的代码。极好的。 我不是创造者,只是一个快乐的用户。

    【讨论】:

      【解决方案7】:

      遇到了同样的问题:Storyboard 中为 TextView 设置的属性字体在 XCode 6.1 和 iOS 8 SDK 的运行时不起作用。

      这就是我解决此问题的方法,可能是您的解决方法:

      1. 打开文本视图的属性检查器,将文本更改为 “普通”

      2. 点击十字删除“wC hR”(下图红色)

      3. 将文本更改为“Attributed”,然后可以设置字体和大小 为你的文字。

      4. 运行以检查它是否有效

      【讨论】:

      • 似乎默认没有设置wC hR属性,既没有UILabel也没有UITextView
      • by xcode 6,你是否设置了另一种高度-宽度,例如“常规宽度 | 任意高度”、“紧凑宽度 | 常规高度”?因为我有一个在 Xcode 5 中开发的项目,并且它的属性 textview 甚至可以使用 iOS 8 SDK,我检查了那里的设置,发现唯一的区别是 Xcode 6 允许用户为不同大小的设备设置字体,如果你设置文本“清楚的”。这种新配置可能是在“属性”中设置文本但字体不起作用的原因。
      • 您使用的是自定义字体吗?我的意思是自嵌入字体,而不是系统字体。
      • 啊哈,我认为您提到的“自定义”字体是 Xcode 提供的字体,前提是它具有“系统”字体。
      • 它对我不起作用。它适用于普通字符串,但不适用于属性字符串。
      【解决方案8】:

      遇到了同样的问题:情节提要中 UILabel 的属性字体在运行时不起作用。使用这个 UIFont+IBCustomFonts.m 对我有用 https://github.com/deni2s/IBCustomFonts

      【讨论】:

        【解决方案9】:

        试试这个就行了

        在我的情况下,当我尝试将“Silversky Technology”设置为来自界面构建器的标签的属性文本时,它在我在模拟器中运行时不显示,但在界面构建器中显示。所以我使用了一个技巧,我使 Silversky 字体比技术文本大 1 个像素。

        属性文本与相同大小的字体有问题,所以改变 1 个字的大小这个对我有用。

        可能这是 xcode 错误,但这个技巧对我有用。

        【讨论】:

          【解决方案10】:

          同样的问题。

          已解决:只需检查 TextView 中的 Selectable。没有这个我有标准的系统字体。

          【讨论】:

            【解决方案11】:

            双击并将字体安装到系统中。它将工作(Xcode 8.2)

            【讨论】:

            • 我希望它会。 FontAwesome 对我不起作用。
            【解决方案12】:

            @Hamidptb 解决方案有效,请确保获取正确的字体名称(将其添加到字体册后)

            • 打开 Font Book 应用程序,导航到您的字体,然后按 Command+I。 PostScript 名称是您要在此处使用的字体名称:

              UILabel.appearance().font = UIFont(name: "PostScriptName", size: 17)

            【讨论】:

              【解决方案13】:

              我试图获取包含多个段落的文本的 tableView 单元格。属性字符串似乎是一种在段落之间获得额外空间的方法(比在字符串中进行两次换行更好看一些)。当我发现当您想在单元格中放置不同的文本时,IB 设置不适用于运行时。

              我想出的主要事情是向 String 添加一个扩展(使用 Swift) 创建具有某些特征的属性字符串。这里的示例使用 Marker Felt 字体,因为它很容易与 Helvetica 区分开来。该示例还显示了段落之间的一些额外间距,以使它们彼此更加不同。

              extension String {
              func toMarkerFelt() -> NSAttributedString {
                  var style = NSMutableParagraphStyle()
                  style.paragraphSpacing = 5.0
                  let markerFontAttributes : [NSObject : AnyObject]? = [
                      NSFontAttributeName : UIFont(name: "Marker Felt", size: 14.0)!,
                      NSParagraphStyleAttributeName: style,
                      NSForegroundColorAttributeName : UIColor.blackColor()
                  ]
                  let s = NSAttributedString(string: self, attributes: markerFontAttributes)
                  return s
                  }
              }
              

              然后,在我的自定义 tableViewCell 中,您将所需的文本发送给它,然后它将其转换为 UILabel 上的属性字符串。

              //  MarkerFeltCell.swift
              class MarkerFeltCell: UITableViewCell {
              @IBOutlet weak var myLabel: UILabel!
              func configureCellWithString(inputString : String) {
                  myLabel.attributedText = inputString.toMarkerFelt()
              }}
              

              在带有 tableView 的视图控制器中,您应该在 viewDidLoad() 中注册您的单元格——我使用了一个 nib,所以类似于:

              let cellName = "MarkerFeltCell"
              tableView.registerNib(UINib(nibName: cellName, bundle: nil), forCellReuseIdentifier: cellName)
              

              要让单元格弄清楚它应该有多高,请制作一个原型单元格,用于获取大小信息,并且永远不会添加到 tableView 中。所以,在你的 查看控制器的变量:

              var prototypeSummaryCell : MarkerFeltCell? = nil
              

              然后在(可能覆盖 - 取决于您的视图控制器)heightForRowAtIndexPath:

              override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
                      // ...
                  if xib == "MarkerFeltCell" {
                          if prototypeCell == nil {
                              prototypeCell = tableView.dequeueReusableCellWithIdentifier(xib) as? MarkerFeltCell
                          }
                          let width : CGFloat = tableView.bounds.width
                          let height : CGFloat = prototypeCell!.bounds.height
                          prototypeCell?.bounds = CGRect(x: 0, y: 0, width: width, height: height)
                          configureCell(prototypeCell!, atIndexPath: indexPath)
                          prototypeSummaryCell?.layoutIfNeeded()
                          let size = prototypeSummaryCell!.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
                          let nextHeight : CGFloat = ceil(size.height + 1.0)
                          return nextHeight
                  } else {  // ...
              

              在上面的代码中,prototypeCell会在第一次需要的时候填充。在完成自动调整大小过程后,prototypeCell 然后用于计算单元格的高度。您需要使用 ceil() 函数对高度进行四舍五入。我还添加了一些额外的软糖因素。

              最后的代码位是您如何配置单元格的文本。对于此示例,只需:

              func configureCell(cell :UITableViewCell, atIndexPath indexPath: NSIndexPath) {
                  if let realCell = cell as? MarkerFeltCell  {
                      realCell.configureCellWithString("Multi-line string.\nLine 2.\nLine 3.")    // Use \n to separate lines
                  }
              }
              

              另外,这是笔尖的照片。将标签固定到单元格的边缘(需要边距),但使用“大于或等于”约束,底部约束的优先级低于“必需”。

              将标签的字体设置为 Attributed。实际的 IB 字体无关紧要。

              这种情况下的结果:

              【讨论】:

                【解决方案14】:

                如果是属性字符串,您可以在字体列表中添加自定义字体 - 单击字体图标,这将显示以下对话框。在以下对话框中,您可以添加自己的类别或现有的自定义字体类别。attributed font dialog

                点击管理字体后,它会打开以下对话框,选择您创建的或现有的类别中的类别。单击 + 号以在类别中添加字体。 Manage font dialog

                【讨论】:

                  【解决方案15】:

                  这是一个简单而快速的解决方案,这对我来说是有效的。 该解决方案是在 AppDelegate.swift 文件的 didFinishLaunchingWithOptions 函数中添加代码行:

                  对于文本视图

                  UITextView.appearance().font = UIFont(name: "IranSans", size: 17)
                  

                  标签

                  UILabel.appearance().font = UIFont(name: "IranSans", size: 17)
                  

                  对于 UiView 的其余部分,就像这两个 ☝️

                  【讨论】:

                    【解决方案16】:

                    对于将自定义字体应用于代码中的属性字符串的任何人:尝试将其设置为 viewDidLayoutSubviews。我的错误是在viewDidLoad 中做的,它不会在那里应用。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2022-08-20
                      • 1970-01-01
                      • 2015-09-03
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-01-19
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多