Xcode 6 Size Classs中的自定义字体大小无法与自定义字体一起正常使用


104

xcode的6有一个新的特征,其中的字体字体大小UILabelUITextFieldUIButton可自动基于尺寸类当前设备配置的设定,就在情节串连图板。例如,您可以将a设置为UILabel在“任何宽度,紧凑高度”配置(例如,在横向iPhone上)上使用12号字体,在“常规宽度,常规高度”配置(例如,在iPad上)上使用18号字体。更多信息请点击这里:

developer.apple.com/size_class

从理论上讲,这是一个很棒的功能,因为它可能不需要基于设备配置以编程方式在UI功能上设置不同的字体。现在,我有一些条件代码可以根据设备类型设置字体,但是很明显,这意味着我必须在整个应用中的所有位置以编程方式设置字体。因此,最初,我对该功能感到非常兴奋,但是我发现它对我的实际使用存在严重问题(可能是一个错误)。请注意,我正在针对SDK 8构建并设置iOS 8的最低部署目标,因此这与与旧版本的iOS的兼容性无关。

问题是这样的: 如果我为不同的大小级别设置了不同的字体大小,并使用iOS提供的“系统”字体,那么一切都会按预期工作,并且字体大小会根据大小级别而变化。如果我使用应用程序提供的自定义字体(是的,我已经在我的应用程序捆绑包中正确设置了它,因为它可以以编程方式工作),并将该自定义字体设置为XCode 6故事板中标签,该标签也可以按预期工作。但是,当我尝试对不同大小的类使用不同大小的自定义字体时,在情节提要中,它突然不起作用。配置上的唯一区别是我选择的字体(自定义字体与系统字体)。相反,所有字体都显示在装置和仿真器默认系统字体默认大小,无论大小类(我通过调试器,它是替代在故事板中指定的实际一个系统字体验证)。因此,基本上,自定义字体的大小类功能似乎已损坏。另外,有趣的是,自定义字体实际上在视图控制器的XCode 6“预览”窗格中正确显示和调整大小:仅当在实际的iOS系统上运行时,它才会停止工作(这使我认为我在正确配置它) 。

我尝试了多种不同的自定义字体,但它们似乎不适用于其中任何一种,但是如果我改用“系统”,它将始终有效。

无论如何,还有其他人在Xcode 6中看到此问题吗?

关于这是否是iOS 8,Xcode或其他错误的任何想法

我做错了吗?

正如我所说,我发现的唯一解决方法是继续以编程方式设置字体,就像我在大约三个iOS版本中一样,因为它确实可以工作。

但是,如果可以使用自定义字体,我希望能够使用此功能。我们的设计不接受使用系统字体。


其他信息: 从Xcode 8.0开始,该错误已修复。


3
我可以确认在xCode 6.1(6A1052d)应用商店版本中仍然如此。
2014年

3
不是解决方案,但是我设法使用Category来解决此问题。我的类别UILabel + Font.h(我也有一个按钮)包含以下代码。-(void)awakeFromNib {float size = [self.font pointSize]; self.font = [UIFont fontWithName:@“ YourCustomFont” size:size]; }因此,这允许我们使用带有System字体的大小类来设置不同大小类中的点值,并且该类别确保设置了正确的字体。也许您可以放手一搏,直到Apple发布更新?
Daniel Retief Fourie

2
在Xcode 6.3.1中仍未解决。我对此很生气。
愤怒2015年

7
仍无法使用Xcode 7 final。不明白为什么苹果不修复它。
ernesto

5
仍无法在Xcode 7.2 iOS 9.2上使用
Mojtaba 2015年

Answers:


41

快速修复:

1)将字体设置为大小类的系统

标签属性检查器

2)子类化UILabel并覆盖“ layoutSubviews”方法,例如:

- (void)layoutSubviews
{
  [super layoutSubviews];

   // Implement font logic depending on screen size
    if ([self.font.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location == NSNotFound) {
        NSLog(@"font is not bold");
        self.font = [UIFont fontWithName:@"Custom regular Font" size:self.font.pointSize];
    } else {
        NSLog(@"font is bold");
        self.font = [UIFont fontWithName:@"Custom bold Font" size:self.font.pointSize];
    }

}

顺便说一句,这是一种非常方便的图标字体技术


如果在整个应用程序中使用的字体是相同的,这是一个很好的解决方法,但是如果您需要在不同的地方使用不同的字体,则不太方便,因为那样的话您必须具有不同的子类,等等。设置了程序化字体,并且有很多不同的方法可以执行此操作。但是我的问题不是要问如何以编程方式执行此操作:而是要问为什么使用Storyboards不能正常工作(这是Apple的错误)。
mnemia

@mnemia我同意。我的目的只是说明如何处理该错误。
razor28

1
效果很好。但是,您不需要子类化UILabel,您可以仅在保存标签的视图中重写此方法,然后执行self.label.font = ...此操作。这样,您可以在不同的位置使用不同的字体。
KPM

或者,您可以设置一个@IBInspectable,以存储字体名称,重用相同的自定义标签类并直接在情节提要中请求不同的字体。
Craig Grummitt 2015年

UITextField是否有类似的解决方案?
克里斯·拜亚特

17

经过一切尝试,我最终选择了上述解决方案的组合。使用Xcode 7.2,Swift 2。

import UIKit

class LabelDeviceClass : UILabel {

    @IBInspectable var iPhoneSize:CGFloat = 0 {
        didSet {
            if isPhone() {
                overrideFontSize(iPhoneSize)
            }
        }
    }

    @IBInspectable var iPadSize:CGFloat = 0 {
        didSet {
            if isPad() {
                overrideFontSize(iPadSize)
            }
        }
    }

    func isPhone() -> Bool {
        // return UIDevice.currentDevice().userInterfaceIdiom == .Phone
        return !isPad()
    }

    func isPad() -> Bool {
        // return UIDevice.currentDevice().userInterfaceIdiom == .Pad
        switch (UIScreen.mainScreen().traitCollection.horizontalSizeClass, UIScreen.mainScreen().traitCollection.verticalSizeClass) {
        case (.Regular, .Regular):
            return true
        default:
            return false
        }
    }

    func overrideFontSize(fontSize:CGFloat){
        let currentFontName = self.font.fontName
        if let calculatedFont = UIFont(name: currentFontName, size: fontSize) {
            self.font = calculatedFont
        }
    }

}
  • @IBInspectable 让您在情节提要中设置字体大小
  • 它使用didSet观察器来避免陷阱 layoutSubviews()(动态表视图行高的无限循环)和awakeFromNib()(请参阅@cocoaNoob的评论)
  • 它使用大小类而不是设备惯用语,希望最终将其与 @IBDesignable
  • 可悲的是,根据另一篇文章@IBDesignable它不起作用traitCollection
  • 特征收集开关语句是在UIScreen.mainScreen()而不是在self堆栈文章上执行的

最好的答案,但可惜在投票下..谢谢
Rohit Pradhan

9

解决方法UILabel:保持对所有大小的类相同的字体大小,而是在每一个尺寸级别进行相应的更改标签的高度。您的标签必须启用自动收缩功能。就我而言,它工作得很好。


1
通过更改每个Size Class中的标签宽度,我能够执行相同的操作。好提示!
dmzza

1
我没有通过为UILabel设置较小的固定高度来缩小字体,请问您是如何工作的呢?adjustsFontSizeToFitWidth似乎只适用于宽度(我不能使用,因为标签的文本是动态的)。
ernesto

我在调整宽度时遇到相同的问题
Jules 2015年

1
我最终将标签的高度约束设置为与超级视图的高度成比例。这工作得很好,只要你设置在IB标签的“线”参数为0
多利安罗伊

8

这个(以及其他与Xcode-Size Classs相关的)错误最近让我感到非常悲伤,因为我不得不经历一个巨大的演示图板文件,将某些东西砍掉。

对于这个职位上的其他人,我想在@ razor28的答案之上添加一些内容以减轻痛苦。

在自定义子类的头文件中,将其IBInspectable用于运行时属性。这将使这些属性可以从“属性检查器”中访问,该属性在字体设置的默认位置的正上方。

使用示例:

@interface MyCustomLabel : UILabel

    @property (nonatomic) IBInspectable NSString *fontType;
    @property (nonatomic) IBInspectable CGFloat iphoneFontSize;
    @property (nonatomic) IBInspectable CGFloat ipadFontSize;

@end

这将非常有帮助地产生以下输出:

在此处输入图片说明

另一个好处是,现在我们不必为每个标签手动添加运行时属性。这是我最接近XCode预期行为的方式。希望今年夏天可以在iOS 9上进行适当的修复。


我已按照您的指示添加,但无法在xib中直观地找到访问“属性检查器”,因此如何实现呢?
Darshan Kunjadiya'3

3

与@ razor28的解决方案类似,但我认为通用性更高。此外,在较旧的iOS版本上也可以正常工作

https://gist.github.com/softmaxsg/8a3ce30331f9f07f023e


并且可以肯定的是,您可以在Interface Builder中设置属性overrideFontName,从而避免编写不必要的代码
Vitaly 2015年

这对我不起作用,我列出了上述方法中所有已安装的字体,并且列出了字体并在变量中分配了我的字体,但是没有更改模拟器上标签上的字体显示,我假设使用设备
Jules

3

该错误在XCode 7.0 GM中仍然有效。

Razor28的解决方案在某些情况下会导致无限循环。我的经验是将它与SwipeView结合使用。

相反,我建议您:

1)子类 UILabel并覆盖setFont:

- (void)setFont:(UIFont *)font
{
    font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize];
    [super setFont:font];
}

2)设置 UILabels 的自定义类,然后使用系统字体设置字体大小类

在此处输入图片说明


@ Maarten1909您是指解决方法还是简单的XCode方法?如果是第一个,请指定版本,以便我尝试复制它?
Foti Dim 2015年

似乎我一直都在使用错误的字体系列名称。事实证明,在这种情况下,字体被重置为14.0品脱大小的系统字体。我的错。但这可能对其他人有用!
Berendschot

0

问题仍然存在,您无法使用该功能从界面生成器为不同大小的类设置字体。

只需根据您想要的设备设置字体,如下所示:

if (Your Device is iPAd) //For iPad
{
   [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; 
}
else  //For Other Devices then iPad
{
   [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; 
}

这在所有设备上均能完美运行。


0

这些都不对我有用,但确实如此。您还需要在IB中使用系统字体

#import <UIKit/UIKit.h>

@interface UILabelEx : UILabel


@end

#import "UILabelEx.h"
#import "Constants.h"

@implementation UILabelEx

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
    [super traitCollectionDidChange: previousTraitCollection];

    self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize];   
}
@end

0

仍然没有签名的正确答案。这段代码对我来说很好用。您必须首先在界面构建器中禁用字体大小。在IB中,您可以使用自定义字体。

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
    [super traitCollectionDidChange: previousTraitCollection];

    if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass)
        || self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass) {

         self.textField.font = [UIFont fontWithName:textField.font.fontName size:17.f];

    }
}

0

上面的一些稍后答案的组合是有帮助的。这是我通过Swift UILabel扩展解决IB错误的方法:

import UIKit

// This extension is only required as a work-around to an interface builder bug in XCode 7.3.1
// When custom fonts are set per size class, they are reset to a small system font
// In order for this extension to work, you must set the fonts in IB to System
// We are switching any instances of ".SFUIDisplay-Bold" to "MuseoSans-700" and ".SFUIDisplay-Regular" to "MuseoSans-300" and keeping the same point size as specified in IB

extension UILabel {
    override public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass) {
            //let oldFontName = "\(font.fontName)-\(font.pointSize)"

            if (font.fontName == systemFontRegular) {
                font = UIFont(name: customFontRegular, size: (font?.pointSize)!)
                //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
            }
            else if (font.fontName == systemFontBold) {
                font = UIFont(name: customFontBold, size: (font?.pointSize)!)
                //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
            }
        }
    }
}

-1

我正在使用Swift,XCode 6.4。这就是我所做的

import Foundation
import UIKit

    @IBDesignable class ExUILabel: UILabel {

        @IBInspectable var fontName: String = "Default-Font" {
            didSet {
                self.font = UIFont(name: fontName, size:self.font.pointSize)
            }
        }

        override func layoutSubviews() {
            super.layoutSubviews()
            self.font = UIFont(name: fontName, size:self.font.pointSize)
        }
    }
  1. 转到设计器->身份检查器->将类设置为ExUILabel

  2. 然后转到设计器中的“属性检查器”并设置字体名称。


-1

我提出了更快的解决方案(我假设您始终使用一种自定义字体)。

为UILabel创建一个类别,并使用具有多个大小级别和各种级别的专用字体设置的越野车故事板将其包含在文件中:

@implementation UILabel (FontFixForSizeClassesAppleBug)

- (void)layoutSubviews
{
    [super layoutSubviews];
    if([[UIFont systemFontOfSize:10].familyName isEqualToString:self.font.familyName]) {
        //workaround for interface builder size classes bug which ignores custom font if various classes defined for label: http://stackoverflow.com/questions/26166737/custom-font-sizing-in-xcode6-size-classes-not-working-properly-w-custom-fonts
        self.font = [UIFont fontWithName:@"YOUR_CUSTOM_FONT_NAME" size:self.font.pointSize];
    }
}

@end

只需在情节提要中使用自定义字体即可。当越野车解释器将使用系统字体而不是您自己的字体时,此类别会将其切换到您的自定义字体。


-1:重写此类中的方法不是一个好主意。原因:stackoverflow.com/questions/5272451/… 相反,应该混乱(尽管很hacky)或子类。
JRG-Developer's

-6

我遇到了同样的问题,发现一个不是很清楚,但是很好的解决方案!

  1. 首先,使用系统字体名称在情节提要中设置所需的字体大小。
  2. 然后为该标签分配一个从100到110的标签(或更多,但在一个视图控制器中10足以满足我的需要)。
  3. 然后将此代码放入VC的源文件中,不要忘记更改字体名称。快速编写代码。
override func viewDidLayoutSubviews() {
    for i in 100...110 {
        if let label = view.viewWithTag(i) as? UILabel {
            label.font = UIFont(name: "RotondaC-Bold", size: label.font.pointSize)
        }
    }
}

1
不要使用标签。使用IBOutlets。标签不好。请参阅WWDC 2015会话231:“如果您正在使用带标签的视图或设置标签的UIView API和运输代码,我将鼓励您远离它。作为对此的替代,请在类上声明属性,然后您将与以后需要的那些视图建立真正的联系。”
KPM

我感到遗憾的是,该解决方案并不完美,但可以正常工作!
serg_ov

-8
  • 将应用程序提供的字体添加到应用程序.plist中
  • 将您的.ttf文件添加到项目0
  • 使用它[UIFont fontWithName:“ example.ttf” size:10]

这不是这个问题的答案。显然,您可以通过编程方式使用自定义字体,但是我的问题是iOS 8中的一个错误,该错误阻止自定义字体根据大小类自动更改。
mnemia
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.