故事板中带有自定义字体的属性字符串无法正确加载


100

我们在项目中使用自定义字体。它在Xcode 5中运行良好。在Xcode 6中,它在纯文本(代码中的属性字符串)中运行。但是,在演示板或设备上运行时,在情节提要中设置的那些归因字符串都将还原为Helvetica,尽管它们在情节提要中看起来还不错。

我不确定这是Xcode 6还是iOS 8 SDK的错误,还是Xcode 6 / iOS 8中更改了自定义字体的使用方式?


这里同样的问题。很想知道怎么回事。
obeattie 2014年

1
现在,我们创建了一个自定义UILabel(名为GLMarkdownLabel),并使用IBInspectable导出了一些属性,然后在情节提要中设置markdown字符串,并在从笔尖唤醒后将markdown字符串转换回属性字符串。
许志安2014年

现在这是一个长期解决方案,希望苹果公司将在下一版本的Xcode中修复此错误。
许志安2014年

kes,真是cru脚。感谢您让我们知道这不是一个孤立的问题。有雷达吗?
obeattie

1
我们的解决方法最终是回到对属性标签使用IBCustomFonts
yonix 2014年

Answers:


30

对我来说,解决方法是使用一个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自定义字体

您可以像平常一样设置attributedstring,但是必须在新的可用属性中再次设置fontsize和fontfamily。

由于Interface Builder在默认情况下使用自定义字体,因此生成的内容就是您所看到的,这是我在构建应用程序时更喜欢的。

注意

我之所以使用它而不是普通版本,是因为我在属性标签上设置了属性,例如linepacing,这在使用普通样式时不可用。


1
您的解决方案仅支持一种标签的字体系列和大小,那么为什么不只使用纯文本呢?
许志安2014年

同样,我们@IBInspectable暂时使用属性,而不是字体和大小。我们有一个markdownText属性,因为在大多数情况下,我们将属性字符串用于粗体或带下划线的文本。然后将markdown文本解析为具有为纯文本设置的字体和大小信息的属性字符串。
许志安2014年

@AllenHsu,你是对的。没提到,但是我在标签上使用了属性的行距。偏离路线,否则您只需要使用简单的样式即可:)
Antoine

好点,我们也导出了lineSpacing:p我想我会接受您的回答,因为它实际上是Xcode中的错误,目前没有更好的解决方案。让我们等待下一个Xcode版本。
许志安2014年

2
如果我要加粗文本的一部分,将无法使用
xtrinch

28

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


17
尽管这将使Xcode选择自定义字体,但实际上不起作用。在运行时,将不会像您期望的那样使用该字体。
丹尼尔(Daniel)

不幸的是,我无法提出解决方法。我能做的最好的事情就是与Apple一起记录错误。
丹尼尔(Daniel)

是的,这就是解决方法。我的故事板是由另一位开发人员设计的,svn update ok,但从未在UI中获得字体。字体在资源中,但未在设备/模拟器UI中显示。由于他使用属性字符串,因此我必须在“字体书”中使用它。那解决了问题。
karim

是。这可以帮助我解决相同的问题。当我将自定义字体添加到字体书中时,其工作原理就像是魅力。
Sushant Jagtap '18年

1
尽管此解决方案在某些情况下可行,但在同一项目中使用相同字体系列的@Daniel,我也遇到了同样的问题。XCode需要解决此问题。
dey.shin

16

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

步骤1:点击管理字体。它打开字体书。

在此处输入图片说明

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

在此处输入图片说明

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


这确实可以在情节提要中起作用,但运行后不会显示格式
Van Van

1
@范格式?你能告诉我更多吗?什么时候不起作用?
mahbaleshwar hegde

我必须设置rgualr和粗体字体的混合匹配的文本。我使用了上面的解决方案,所以它在情节提要中起作用,但是当我运行该应用程序时,标签没有显示所应用的字体,而是显示了系统字体
Van

您是否在info.plist中添加了自定义字体?之后,只需打印所有字体系列
mahbaleshwar hegde

2
是。在纯文本的情况下,我可以在整个应用程序中设置自定义字体,我需要为属性文本设置
Van Van

5

感谢这个线程,我来到了这个解决方案:

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
}

1
好主意。真令人难以置信,这在Apple中已被打破。惊人。
Fattie

4

我的解决方案有点变通。真正的解决方案是让Apple修复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;
}

受此职位启发


4

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

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


3

遇到了同样的问题:在故事板中为TextView设置的属性字体在运行时不适用于XCode 6.1和iOS 8 SDK。

这是我解决此问题的方式,可能对您来说是一种解决方法:

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

  2. 单击十字架以删除“ wC hR”(下面的红色)

    在此处输入图片说明

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

  4. 跑去检查是否有效

似乎默认情况下没有wC hR设置属性,也UILabel没有设置UITextView
许志安2014年

通过xcode 6,您是否设置了另一种高度-宽度,例如“常规宽度|任何高度”,“紧凑宽度|常规高度”?因为我有一个用Xcode 5开发的项目,并且即使使用iOS 8 SDK,它的属性textview也可以工作,所以我检查了那里的设置,发现唯一的区别是Xcode 6允许用户在不同尺寸的设备上设置字体,如果您在“平原”。此新配置可能是为什么在“属性”中设置文本但字体无法正常工作的原因。
杨志豪2014年

1
您在使用自定义字体吗?我的意思是自我嵌入的,而不是系统字体。
许志安2014年

啊哈,我想您提到的“自定义”字体是Xcode提供的字体,前提是它具有字体“ System”。
皓阳

它对我不起作用。它适用于普通字符串,但不适用于属性字符串。
Pratik Somaiya


2

试试这个会起作用

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

属性文字的字体大小相同,因此更改1个字的大小就可以了。

可能这是xcode的错误,但这对我有用。


1

一样的问题。

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



1

@Hamidptb解决方案有效,请确保获得正确的字体名称(一旦将其添加到“字体书”中)

  • 打开“字体书”应用程序,导航到您的字体,然后按Command + I。该的PostScript名字是你想在这里使用的字体名称:

    UILabel.appearance()。font = UIFont(name:“ PostScriptName ”,大小:17)


0

我试图获取带有多段文字的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()中注册单元格-我使用了笔尖,所以类似:

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
    }
}

另外,这里是笔尖的镜头。将标签固定到单元格的边缘(具有所需的边距),但使用“大于或等于”约束,对底部约束的优先级小于“必需”的约束。

单元约束

将标签的字体设置为“属性”。实际的IB字体无关紧要。

标签字体

在这种情况下的结果:

细胞结果


0

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

单击“ 管理字体”后,将打开以下对话框,在您创建或现有的对话框中选择类别。单击+号在类别中添加字体。 管理字体对话框


0

这是一个简单快捷的解决方案,对我来说就是这样。该解决方案是在AppDelegate.swift文件的didFinishLaunchingWithOptions func中添加代码行:

对于textViews

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

用于标签

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

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


0

对于在代码中将自定义字体应用于属性字符串的任何人:尝试在中进行设置viewDidLayoutSubviews。我的错误是在中执行此操作viewDidLoad,因此无法在其中应用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.