Xcode 6中的自定义字体大小使用自定义字体无法正常使用大小类

时间:2014-10-02 18:01:53

标签: ios interface-builder ios8 xcode6 size-classes

Xcode 6具有一项新功能,可以在故事板中根据当前设备配置的大小类自动设置UILabel,UITextField和UIButton中的字体和字体大小。例如,您可以将UILabel设置为在"任何宽度,紧凑高度"上使用字体大小12。 (例如在风景中的iPhone上)配置和尺寸18在"规则宽度,常规高度"配置(例如在iPad上)。有关更多信息,请访问:

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/Size-ClassSpecificLayout.html

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

问题在于: 如果我为不同的大小类设置不同的字体大小,并使用"系统"由iOS提供的字体,一切都按预期工作,字体大小根据大小类更改。如果我使用我的应用程序提供的自定义字体(是的,我在应用程序包中正确设置,因为它以编程方式工作)并将自定义字体设置为XCode 6故事板中的标签,这也可以按预期工作。但是当我尝试为不同大小的类使用不同大小的自定义字体时,在故事板中,它突然不起作用。配置的唯一区别是我选择的字体(自定义字体与系统字体)。相反,所有字体都显示在设备和模拟器上作为默认大小的默认系统字体,无论大小等级(我通过调试器验证它是用系统字体替换故事板中指定的实际字体) 。所以基本上,自定义字体的大小类功能似乎已被破坏。另外,有趣的是,自定义字体实际上在XCode 6"预览"中正确显示和调整大小。视图控制器的窗格:它只有在实际的iOS系统上运行时才会停止工作(这让我觉得我正确配置它)。

我尝试了多种不同的自定义字体,它似乎并不适用于任何一种字体,但是如果我使用" System"它总是有用的。代替。

无论如何,还有其他人在Xcode 6中看到过这个问题吗?关于这是否是iOS 8,Xcode中的错误或者我做错了什么的任何想法?我发现,我发现的唯一解决方法是继续以编程方式设置字体,就像我对大约3个版本的iOS一样,因为这确实有效。但是我希望能够使用此功能,如果我可以使用自定义字体。我们的设计不接受使用System字体。


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

13 个答案:

答案 0 :(得分:40)

快速修复:

1)将字体设置为System for size size

Label attributes inspector

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

}

顺便说一下,这是一种非常方便的标志性字体技术

答案 1 :(得分: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可让您在Storyboard
  • 中设置字体大小
  • 它使用didSet观察者,以避免layoutSubviews()(动态表格视图行高度的无限循环)和awakeFromNib()(参见@ cocoaNoob' s评论)中的陷阱/ LI>
  • 它使用大小类而不是设备习惯用法,希望最终在@IBDesignable
  • 中使用它
  • 可悲的是,根据其他stack article
  • @IBDesignable无法与traitCollection合作
  • 特征收集开关语句在UIScreen.mainScreen()而不是self上执行stack article

答案 2 :(得分:9)

UILabel

解决方法:在所有尺寸类上保持相同的字体大小,而是在每个尺寸类中相应地更改标签高度。您的标签必须启用自动收缩功能。在我的案例中它很好用。

答案 3 :(得分:8)

这个(和其他Xcode - Size Classes相关的)错误最近给我带来了一些严重的悲痛,因为我不得不通过一个巨大的故事板文件来解决问题。

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

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

使用示例:

@interface MyCustomLabel : UILabel

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

@end

这将非常有助于产生此输出:

enter image description here

另一个好处是,现在我们不必为每个标签手动添加运行时属性。这是我最接近XCode的预期行为。希望今年夏天在iOS 9上正确的解决方案。

答案 4 :(得分:3)

与@ razor28相似的解决方案,但我认为更普遍。此外,在较旧的iOS版本上正常工作

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

答案 5 :(得分: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]]; 
}

这适用于所有设备。

答案 6 :(得分: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

答案 7 :(得分: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];

    }
}

答案 8 :(得分: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)")
            }
        }
    }
}

答案 9 :(得分:-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. 转到设计师 - &gt;身份检查员 - &gt;将班级设置为ExUILabel

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

答案 10 :(得分:-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

只需在故事板中使用自定义字体即可。当有缺陷的翻译将使用系统字体而不是你自己的这个类别将它切换到你的自定义字体。

答案 11 :(得分:-6)

我有同样的问题,发现一个不太清楚,但很好的解决方案!

  1. 首先,在storyboard中使用系统字体名称设置所需的字体大小。
  2. 然后在这个标签上你分配一个100到110的标签(或更多,但在一个视图控制器中10对我来说总是足够的。)
  3. 然后将此代码放入VC的源文件中,不要忘记更改字体名称。代码在swift。
  4. 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)
            }
        }
    }
    

答案 12 :(得分:-8)

  • 将应用程序提供的字体添加到您的应用.plist
  • 将您的.ttf文件添加到第0项
  • 使用它[UIFont fontWithName:&#34; example.ttf&#34;尺寸:10]