Xcode 6 크기 클래스의 사용자 정의 글꼴 크기 조정이 사용자 정의 글꼴에서 제대로 작동하지 않음


104

엑스 코드 6 새로운 기능 보유 폰트폰트 사이즈 의은 UILabel, UITextFieldUIButton오른쪽 스토리 보드에 현재 장치 구성의 크기 클래스에 따라 자동으로 설정 될 수있다. 예를 들어, UILabel"모든 너비, 높이 축소"(예 : 가로 방향의 iPhone) 구성에서 글꼴 크기 12를 사용하고 "일반 너비, 일반 높이"구성 (예 : iPad ) 에서 크기 18을 사용하도록 a를 설정할 수 있습니다 . 자세한 정보는 여기에서 확인할 수 있습니다.

developer.apple.com/size_class

이것은 장치 구성에 따라 UI 기능에 다른 글꼴을 프로그래밍 방식으로 설정할 필요가 없기 때문에 이론상 훌륭한 기능입니다. 지금은 장치 유형에 따라 글꼴을 설정하는 조건부 코드가 있지만 분명히 앱 전체에서 글꼴을 프로그래밍 방식으로 설정해야합니다. 그래서 처음에는이 기능에 대해 정말 흥분했지만 실제로 사용하는 데 심각한 문제가 있다는 것을 알게되었습니다 (아마도 버그 일 것입니다). SDK 8 에 대해 빌드 하고 iOS 8 의 최소 ​​배포 대상을 설정 하므로 이전 버전의 iOS와의 호환성과는 아무 관련이 없습니다.

문제는 이것입니다. 다른 크기 클래스에 대해 다른 글꼴 크기를 설정 하고 iOS 에서 제공 하는 "System"글꼴을 사용하면 모든 것이 예상대로 작동하고 크기 클래스에 따라 글꼴 크기가 변경됩니다. 내 응용 프로그램에서 제공하는 사용자 지정 글꼴을 사용하고 (예, 프로그래밍 방식으로 작동하므로 응용 프로그램 번들에 올바르게 설정되어 있음) 사용자 지정 글꼴을 XCode 6 스토리 보드레이블 로 설정하면 예상대로 작동합니다. 하지만 스토리 보드에서 다양한 크기의 클래스에 대해 다른 크기의 사용자 지정 글꼴을 사용하려고하면 갑자기 작동하지 않습니다. 구성의 유일한 차이점은 내가 선택한 글꼴 (사용자 정의 글꼴 대 시스템 글꼴)입니다. 대신 모든 글꼴이장치 및 시뮬레이터 를 크기 클래스에 관계없이 기본 크기기본 시스템 글꼴 로 사용했습니다 (그리고 디버거를 통해 스토리 보드에 지정된 실제 글꼴을 시스템 글꼴로 대체하고 있음을 확인했습니다). 따라서 기본적으로 크기 클래스 기능은 사용자 정의 글꼴에 대해 깨진 것처럼 보입니다. 또한 흥미롭게도 사용자 지정 글꼴은 실제로보기 컨트롤러의 XCode 6 "미리보기"창에서 제대로 표시되고 크기를 조정합니다. 실제 iOS 시스템에서 실행할 때만 작동이 중지됩니다 (올바르게 구성하고 있다고 생각합니다). .

여러 개의 다른 사용자 정의 글꼴을 시도했지만 어떤 글꼴에서도 작동하지 않는 것 같지만 대신 "시스템"을 사용하면 항상 작동합니다.

어쨌든, 다른 사람이 Xcode 6 에서이 문제를 본 적이 있습니까?

이것이 iOS 8, Xcode 또는 무언가의 버그인지에 대한 아이디어

내가 잘못하고 있니?

내가 찾은 유일한 해결 방법은 내가 말했듯이 약 세 가지 버전의 iOS에서와 같이 프로그래밍 방식으로 글꼴을 계속 설정하는 것입니다.

하지만이 기능을 사용자 정의 글꼴과 함께 사용할 수 있다면이 기능을 사용할 수 있기를 바랍니다. 시스템 글꼴을 사용하는 것은 우리의 디자인에 허용되지 않습니다.


추가 정보 : Xcode 8.0부터 버그가 수정되었습니다.


3
xCode 6.1 (6A1052d) 앱 스토어 릴리스에서도 여전히 그렇다는 것을 확인할 수 있습니다.
jodm

3
해결책은 아니지만 카테고리를 사용하여 문제를 해결할 수있었습니다. 내 범주 UILabel + Font.h (버튼에도 하나 있음)에는 다음 코드가 포함되어 있습니다. -(void) awakeFromNib {float 크기 = [self.font pointSize]; self.font = [UIFont fontWithName : @ "YourCustomFont"size : size]; } 따라서 시스템 글꼴과 함께 크기 클래스를 사용하여 다양한 크기 클래스의 포인트 값을 설정할 수 있으며 카테고리는 올바른 글꼴이 설정되었는지 확인합니다. Apple이 업데이트를 발표 할 때까지 그렇게 할 수 있습니까?
Daniel Retief Fourie 2015 년

2
Xcode 6.3.1에서는 아직 해결되지 않았습니다. 나는 이것에 화가 난다.
Fury

7
여전히 Xcode 7 final에서 작동하지 않습니다. Apple이 왜 그것을 고치지 않는지 이해하지 마십시오.
ernesto 2015 년

5
Xcode 7.2 iOS 9.2에서 여전히 작동하지 않음
Mojtaba 2015

답변:


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

}

그건 그렇고, 그것은 상징적 인 글꼴에 매우 편리한 기술입니다


이 방법은 앱 전체에서 사용되는 글꼴이 동일한 경우 좋은 해결 방법이지만 다른 위치에서 다른 글꼴을 사용해야하는 경우에는 약간 덜 편리합니다. 다른 하위 클래스 등을 가져야하기 때문입니다. 제 경우에는 이미 프로그래밍 방식 글꼴을 설정했으며이를 수행 할 수있는 다양한 방법이 있습니다. 그러나 내 질문의 요점은 프로그래밍 방식으로이 작업을 수행하는 방법을 묻는 것이 아닙니다. 스토리 보드를 사용하여 제대로 작동하지 않는 이유를 묻는 것입니다 (Apple 버그입니다).
mnemia

@mnemia 동의합니다. 내 목표는 그 버그를 어떻게 처리하는지 한 가지 방법으로 보여주는 것입니다.
razor28

1
잘 작동합니다. 하지만 UILabel을 하위 클래스화할 필요는 없습니다. 레이블이있는 뷰에서이 메서드를 재정의하고 self.label.font = ...이렇게하면 다른 위치에서 다른 글꼴을 사용할 수 있습니다.
KPM

또는 @IBInspectable을 설정하여 글꼴 이름을 저장하고 동일한 사용자 정의 레이블 클래스를 재사용하고 스토리 보드에서 직접 다른 글꼴을 요청할 수 있습니다.
Craig Grummitt 2015-10-16

UITextField에 대한 유사한 솔루션이 있습니까?
크리스 Byatt

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
  • 스택 기사를 기준 으로 UIScreen.mainScreen()하는 것이 아니라 트레이 트 수집 스위치 문이 수행됩니다.self

우수 답변, 그러나 슬프게도 Voted..Thanks에서
Rohit 프라

9

해결 방법 에 대한 UILabel모든 크기의 클래스에 같은 글꼴 크기를 유지하는 대신 각 크기 클래스에 따라 레이블 높이를 변경합니다. 레이블에 자동 축소가 활성화되어 있어야합니다. 제 경우에는 잘 작동했습니다.


1
각 크기 클래스에서 레이블 너비를 변경하여 동일한 작업을 수행 할 수있었습니다. 좋은 팁!
dmzza 2015-08-26

1
UILabel의 고정 높이를 더 작게 설정하여 글꼴을 축소하지 못했습니다. 정확히 어떻게 작동하게 되었습니까? adjustsFontSizeToFitWidth너비에 대해서만 작동하는 것 같습니다 (라벨의 텍스트가 동적이기 때문에 사용할 수 없습니다).
ernesto 2015 년

너비에 맞게 조정하는 것과 동일한 문제가 있습니다
Jules

1
결국 Superview의 높이에 비례하여 Label의 높이 제약을 설정했습니다. 당신이 0으로 IB에있는 라벨의 "라인"매개 변수를 설정 한대로 그 길이로 잘 작동
도리안 로이에게

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

이것은 다음과 같은 출력을 매우 유용하게 생성합니다.

여기에 이미지 설명 입력

추가 된 이점은 이제 각 레이블에 대해 런타임 속성을 수동으로 추가 할 필요가 없다는 것입니다. 이것은 XCode의 의도 된 동작에 가장 가깝습니다. 올 여름 iOS 9에서 적절한 수정이 이루어지기를 바랍니다.


나는 당신의 지시에 따라 추가했지만 xib에서 시각적으로 "속성 검사기"에 대한 액세스를 찾을 수 없으므로 어떻게 얻을 수 있습니까?
Darshan Kunjadiya

3

@ razor28의 솔루션과 유사한 솔루션이지만 조금 더 보편적이라고 생각합니다. 또한 이전 iOS 버전에서 잘 작동합니다.

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


그리고 불필요한 코드 작성을 피할 수있는 Interface Builder에서 overrideFontName 속성을 설정할 수 있습니다.
Vitaly

이것은 나를 위해 작동하지 않았고, 나는 위의 방법 내에서 설치된 모든 글꼴을 나열했고 내 글꼴이 나열되고 변수에 할당되었지만 시뮬레이터의 레이블에서 글꼴 표시를 변경하지 않았으며 장치
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 2015 년

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. Goto Designer-> Identity Inspector-> 클래스를 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/… 대신, (해키이지만) 또는 하위 클래스를 휘 두르어야합니다.
JRG-Developer

-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 jul.

-8
  • 응용 프로그램에서 제공하는 글꼴을 app .plist에 추가하십시오.
  • .ttf 파일을 항목 0에 추가하십시오.
  • 그것을 사용하십시오 [UIFont fontWithName : "example.ttf"size : 10]

이것은이 문제에 대한 답이 아닙니다. 분명히 프로그래밍 방식으로 사용자 정의 글꼴을 사용할 수 있지만 내 질문은 iOS 8의 버그로 크기 클래스에 따라 사용자 정의 글꼴이 자동으로 변경되지 않습니다.
mnemia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.