104

Xcode 6には、 、、およびのフォントフォント サイズを、現在のデバイス構成のサイズ クラスに基づいてストーリーボードで自動的に設定できる新しい機能があります。たとえば、「任意の幅、コンパクトな高さ」(横向きの iPhone など) の構成ではフォント サイズ 12 を使用し、「通常の幅、通常の高さ」の構成 ( iPadなど) ではサイズ 18 を使用するように を設定できます。詳細については、次を参照してください。UILabelUITextFieldUIButtonUILabel

developer.apple.com/size_class

これは、デバイス構成に基づいて UI 機能に異なるフォントをプログラムで設定する必要がなくなる可能性があるため、理論的には優れた機能です。現在、デバイスの種類に基づいてフォントを設定する条件付きコードがありますが、明らかに、アプリ全体のあらゆる場所でフォントをプログラムで設定する必要があります。ですから、最初はこの機能にとても興奮していましたが、実際の使用には重大な問題があることがわかりました (おそらくバグです)。SDK 8に対してビルドし、 iOS 8の最小展開ターゲットを設定していることに注意してください。したがって、これは古いバージョンの iOS との互換性とは関係ありません。

問題は次のとおりです。 サイズ クラスごとに異なるフォント サイズを設定し、 iOSが提供する「システム」フォントを使用すると、すべてが期待どおりに機能し、サイズ クラスに基づいてフォント サイズが変化します。アプリケーションで提供されたカスタム フォントを使用し (プログラムで動作するため、アプリケーション バンドルで正しく設定しています)、カスタム フォントをXCode 6 ストーリーボードのラベルに設定すると、これも期待どおりに動作します。しかし、ストーリーボードで、さまざまなサイズのクラスにさまざまなサイズのカスタム フォントを使用しようとすると、突然機能しなくなります。構成の唯一の違いは、選択したフォントです (カスタム フォントとシステム フォント)。代わりに、すべてのフォントがサイズクラスに関係なく、デバイスとシミュレーターデフォルトのシステムフォントとしてデフォルトサイズで使用します(そして、ストーリーボードで指定された実際のシステムフォントをシステムフォントに置き換えていることをデバッガーで確認しました)。したがって、基本的に、カスタム フォントのサイズ クラス機能は壊れているようです。また、興味深いことに、ビュー コントローラーの XCode 6 の [プレビュー] ペインで、カスタム フォントが実際に表示され、サイズが適切に調整されます。実際の iOS システムで実行している場合にのみ機能しなくなります (これは、正しく構成していると思わせてくれます)。 .

複数の異なるカスタム フォントを試しましたが、どのフォントでも機能しないようですが、代わりに「システム」を使用すると常に機能します。

とにかく、Xcode 6でこの問題を見た人はいますか?

これがiOS 8、Xcode、または何かのバグであるかどうかについてのアイデア

私は間違っていますか?

私が見つけた唯一の回避策は、私が言ったように、iOS の約 3 つのバージョンで行ったようにプログラムでフォントを設定し続けることです。

しかし、カスタム フォントで動作させることができれば、この機能を使用できるようになりたいと思っています。システム フォントの使用は、私たちのデザインでは受け入れられません。


追加情報: Xcode 8.0 の時点で、このバグは修正されています。

4

14 に答える 14

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

}

ちなみに、アイコニックフォントにはとても便利なテクニックです

于 2015-01-22T09:43:53.283 に答える
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ストーリーボードのフォント サイズを設定できます
  • (動的テーブルビューの行の高さの無限ループ)および(@cocoaNoobのコメントを参照)didSetからの落とし穴を回避するために 、オブザーバーを使用しますlayoutSubviews()awakeFromNib()
  • 最終的にこれを使用することを期待して、デバイスイディオムではなくサイズクラスを使用します@IBDesignable
  • 残念ながら、この他のスタックの記事によると@IBDesignable動作しませんtraitCollection
  • 特性コレクションの switch ステートメントは、このスタック記事UIScreen.mainScreen()ごとではなくに対して実行されますself
于 2016-01-07T23:38:08.080 に答える
3

@ razor28のソリューションと同様のソリューションですが、もう少し普遍的だと思います。また、古いiOSバージョンでも問題なく動作します

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

于 2015-04-02T20:00:26.110 に答える
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のカスタム クラスを設定し、システム フォントを使用してフォント サイズ クラスを設定します。

ここに画像の説明を入力

于 2015-09-11T09:30:34.463 に答える
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];

    }
}
于 2016-06-19T10:21:46.547 に答える
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)")
            }
        }
    }
}
于 2016-07-06T20:57:39.273 に答える
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
于 2015-11-13T09:15:25.673 に答える
-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. デザイナーに移動 -> Identity Inspector -> クラスを ExUILabel に設定

  2. 次に、デザイナーの属性インスペクターに移動し、フォント名を設定します。

于 2015-09-21T16:37:04.533 に答える
-6

私は同じ問題を抱えていて、本当に明確ではありませんが、良い解決策を見つけました!

  1. 最初に、ストーリーボードで必要なフォント サイズをシステム フォント名で設定します。
  2. 次に、このラベルに 100 から 110 までのタグを割り当てます (またはそれ以上ですが、1 つのビュー コントローラーでは常に 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)
        }
    }
}
于 2015-06-15T13:44:26.587 に答える