Установити шрифт за замовчуванням для цілого додатка iOS?


155

У мене є власний шрифт, який я хочу використовувати для всього, що відображає текст у моїй програмі, мітки, перегляд тексту тощо.

Чи є спосіб встановити шрифт за замовчуванням (мітки за замовчуванням використовують SystemFont) для всього додатка?


7
Масово придивившись до цього лиха. Ми чесно виявили, що найпростіше зробити - це просто створити (тривіальний) новий клас для кожного контролю. Тому для UIButton зробіть SJButton. Не забудьте змінити і initWithFrame, і initWithCode. Для кожного елемента управління (скажімо, UIButton тощо) встановіть кольори або все, що вам подобається. Уважно підберіть скажіть розмір (тобто, це буде розмір SET НА СТОРІБОРД) у коді int, а потім (як вам зручніше) використовувати цей розмір (і встановіть, скажімо, шрифт, колір - будь-який). Це лише кілька рядків коду, неймовірно охайний, і заощаджує вам величезний час у довгостроковій перспективі.
Fattie

@JoeBlow Дякую за публікацію ваших висновків - збирався витратити час на пошуки відповіді, що сам
jj.

@ jj- Правильно. Не забувайте також, що Ви, звичайно, повинні використовувати IBDesignableці дні. Сподіваюся, це допомагає. Також розгляньте цю цікаву QA: stackoverflow.com/a/38000466/294884
Fattie

Відповіді:


158

Здається, це можливо в iOS 5 за допомогою проксі-сервера UIAppearance.

 [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:17.0]];

Це дозволить встановити шрифт таким, яким буде ваш власний шрифт для всіх UILabels у вашій програмі. Потрібно повторити його для кожного елемента управління (UIButton, UILabel тощо).

Пам'ятайте, що вам потрібно буде помістити значення UIAppFonts у свій список info.plist та вказати назву шрифту, який ви включаєте.


46
Дякуємо за відповідь. Мені вдалося змусити це працювати. Чи знаєте ви, чи є спосіб вказати шрифт, не вказуючи розмір шрифту? У моєму додатку є мітки, які не мають однакового розміру шрифту.
Брендон

23
Чи можу я це зробити, не змінюючи розмір точки кожної інстанції?
Майкл Форест

17
setFont:метод застарілий
Ананд

12
@Anand ви впевнені в цьому? Я не бачу, щоб це було як застаріле в UILabel. Він застарілий, UIButtonале він використовує шрифт для titleLabelвластивості, натомість яка є UILabel, тому просто встановлення шрифту з проксі-сервером зовнішнього вигляду UILabelмає бути нормальним.
Адріан Шеніг

6
@Anand не припиняється для UILabel.
Аластер Стюарт

118

Швидкий 5

Спираючись на відповідь Фабіо Олівейри ( https://stackoverflow.com/a/23042694/2082851 ), я роблю власний стрімкий 4.

Коротше кажучи, це розширення обмінів по замовчуванням функція init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:), italicSystemFont(ofSize:)з моїми призначеними для користувача методами.

Зауважте, що це не повністю реалізовано, але ви можете обмінятись більшою кількістю методів на моїй реалізації.

import UIKit

struct AppFontName {
    static let regular = "CourierNewPSMT"
    static let bold = "CourierNewPS-BoldMT"
    static let italic = "CourierNewPS-ItalicMT"
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {
    static var isOverrided: Bool = false

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.regular, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.bold, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.italic, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {
        case "CTFontRegularUsage":
            fontName = AppFontName.regular
        case "CTFontEmphasizedUsage", "CTFontBoldUsage":
            fontName = AppFontName.bold
        case "CTFontObliqueUsage":
            fontName = AppFontName.italic
        default:
            fontName = AppFontName.regular
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }

    class func overrideInitialize() {
        guard self == UIFont.self, !isOverrided else { return }

        // Avoid method swizzling run twice and revert to original initialize function
        isOverrided = true

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        }
    }
}


class AppDelegate: UIResponder, UIApplicationDelegate {
    // Avoid warning of Swift
    // Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions
    override init() {
        super.init()
        UIFont.overrideInitialize()
    }
    ...
}

2
найкраща відповідь !! автоматично перекриває шрифт системи, блискучий
Kappe

2
Якщо у когось є проблеми з рядком "NSCTFontUIUsageAttribute": if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {зробив для мене трюк.
Знання

1
Схоже, не працює з UILabels, який встановлює стиль тексту (жирний, заголовок, заголовок тощо) ... працює лише з шрифтом, який має певний розмір і набір системних шрифтів. @ nahung89
авіран

1
Це також перемикає деякі шрифти системного інтерфейсу. Наприклад, список пропозицій на клавіатурі та аркуш дій. Не знаю, чи це спричинить Apple відхилити додаток
Генрі Х Мяо

1
Минув рік, як ця відповідь була опублікована. Хтось має більш "рідний" спосіб Apple досягти цього?
Грег Хілстон

75

Існує також інше рішення, яке буде перекривати systemFont.

Просто створіть категорію

UIFont + SystemFontOverride.h

#import <UIKit/UIKit.h>

@interface UIFont (SystemFontOverride)
@end

UIFont + SystemFontOverride.m

@implementation UIFont (SystemFontOverride)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

+ (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize {
    return [UIFont fontWithName:@"fontName" size:fontSize];
}

+ (UIFont *)systemFontOfSize:(CGFloat)fontSize {
    return [UIFont fontWithName:@"fontName" size:fontSize];
}

#pragma clang diagnostic pop

@end

Це замінить реалізацію за замовчуванням, і більшість UIControls використовують systemFont.


1
Це в межах яблучних рекомендацій?
Рамбатіно

Це більше хак. Я не додав свій реєстр додатків цим хаком, оскільки він не використовує жодних приватних методів. Якщо ви хочете більш надійне рішення, я також пропоную вам перевірити це: github.com/0xced/FontReplacer
Hugues BR

2
Це добре. Apple просто не хоче, щоб ви використовували незадокументовані функції. Вам дозволено "шикати" загальнодоступними методами.
mxcl

4
Коли категорія має методи з тією ж підписом, що і клас, вона поширює поведінку, не визначена. Для заміни методів класу слід використовувати метод swizzling (що також не є хорошою ідеєю).
GreatWiz

1
Як зазначають інші, це рішення, хоча, ймовірно, діє більшість часу, але технічно вводить потенціал для невизначеної поведінки. Якщо ви не відчуваєте, що ризикуєте, кращим варіантом може стати метод завивання. Відповідь тут забезпечує таке ж рішення , з допомогою swizzling: stackoverflow.com/questions/19542942 / ...
Натан Hosselton

63

Якщо ви використовуєте Swift, ви можете створити розширення UILabel:

extension UILabel {

    @objc var substituteFontName : String {
        get { return self.font.fontName }
        set { self.font = UIFont(name: newValue, size: self.font.pointSize) }
    }

}

І тоді, де ви займаєтесь своєю зовнішністю:

UILabel.appearance().substituteFontName = applicationFont

Існує еквівалентний код Objective-C, який використовується UI_APPEARANCE_SELECTORу властивості з назвою substituteFontName.

Доповнення

Для випадку, коли ви хочете окремо встановити жирні та регулярні шрифти:

extension UILabel {

    @objc var substituteFontName : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") == nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }

    @objc var substituteFontNameBold : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") != nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }
}

Тоді для своїх проксі-представників:

UILabel.appearance().substituteFontName = applicationFont
UILabel.appearance().substituteFontNameBold = applicationFontBold

Примітка. Якщо ви виявите, що жирна заміна не працює, можливо, назва шрифту за замовчуванням не містить "Середній". Вимкніть цей рядок для іншого матчу за потребою (завдяки Мейсону в коментарях нижче).


Одним із недоліків цього, який я виявив, є те, що коли я ініціюю сповіщення за допомогою UIAlertController, кнопка зі стилем .Cancel є такою ж, як кнопка зі стилем .Default (принаймні при використанні GillSans). Тоді як зазвичай .Cancel буде звичайним шрифтом ваги, а .Default буде жирним шрифтом. Будь-які ідеї?
Мейсон Жвіті

Вибачте, я мав на увазі. Мітки відміни зазвичай є жирними, а значення за замовчуванням зазвичай мають звичайну вагу.
Мейсон Жвіті

2
@ MasonG.Zhwiti У такому випадку я, швидше за все, налаштував би UILabelрозширення, щоб взяти додаткову назву шрифту для жирного шрифту. Потім у setперевірці перевірте, чи є "Bold" в назві шрифту, і ігноруйте набір в одному випадку, а використовуйте його в іншому. Я відредагую і додаю приклад.
Сенді Чапман

@SandyChapman Дякую! Я пробую цю нову техніку, і це має сенс, але це, здається, не працює для мене. Я використовую GillSans та GillSans-Bold на тренажері iOS 8.3. Ви протестували цю техніку?
Мейсон Г. Жвіті

2
@SandyChapman я зрозумів, що відбувається. Шрифти за замовчуванням для iOS 8, як правило, є або HelveticaNeueInterface-Regular, або (для жирного шрифту) HelveticaNeueInterface-MediumP4. Тож шукати "Сміливого" ніколи нічого не відповідали. Я змінив це на rangeOfString("Medium")і воно спрацювало.
Мейсон Жвіті

23

Розвиваючись з відповіді Hugues BR, але використовуючи метод swizzling, я прийшов до рішення, яке успішно змінює всі шрифти на потрібний шрифт у моєму додатку.

Підхід з Dynamic Type повинен бути тим, на що слід звернути увагу на iOS 7. У наступному рішенні не використовується Dynamic Type.


Примітки:

  • наведений нижче код, у представленому стані, ніколи не був наданий на затвердження Apple;
  • є його більш коротка версія, яка пройшла подання Apple, тобто без - initWithCoder:перебору. Однак це не охопить усіх справ;
  • наступний код присутній у класі, який я використовую для встановлення стилю моєї програми, що входить до мого класу AppDelegate, таким чином, він буде доступний всюди та для всіх примірників UIFont;
  • Я тут використовую Zapfino лише для того, щоб зміни були значно помітнішими;
  • будь-яке вдосконалення цього коду вітається.

Це рішення використовує два різні методи для досягнення кінцевого результату. Перший - це переосмислення методів класу UIFont + systemFontWithSize:і подібне до тих, що використовують мої альтернативи (тут я використовую "Zapfino", щоб не залишати сумнівів у тому, що заміна була успішною).

Інший метод полягає в тому, щоб замінити - initWithCoder:метод на UIFont, щоб замінити будь-яке виникнення CTFontRegularUsageі подібне моїми альтернативами. Цей останній метод був необхідний, оскільки я виявив, що UILabelоб'єкти, закодовані у файлах NIB, не перевіряють + systemFontWithSize:методи отримання їх системного шрифту, а замість цього кодують їх як UICTFontDescriptorоб'єкти. Я намагався переосмислити, - awakeAfterUsingCoder:але якось це викликало кожен кодований об'єкт в моїй розгортці і спричиняло збої. Переосмислення - awakeFromNibне дозволило б мені прочитати NSCoderоб’єкт.

#import <objc/runtime.h>

NSString *const FORegularFontName = @"Zapfino";
NSString *const FOBoldFontName = @"Zapfino";
NSString *const FOItalicFontName = @"Zapfino";

#pragma mark - UIFont category
@implementation UIFont (CustomFonts)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+ (void)replaceClassSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector {
    Method originalMethod = class_getClassMethod(self, originalSelector);
    Method modifiedMethod = class_getClassMethod(self, modifiedSelector);
    method_exchangeImplementations(originalMethod, modifiedMethod);
}

+ (void)replaceInstanceSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector {
    Method originalDecoderMethod = class_getInstanceMethod(self, originalSelector);
    Method modifiedDecoderMethod = class_getInstanceMethod(self, modifiedSelector);
    method_exchangeImplementations(originalDecoderMethod, modifiedDecoderMethod);
}

+ (UIFont *)regularFontWithSize:(CGFloat)size
{
    return [UIFont fontWithName:FORegularFontName size:size];
}

+ (UIFont *)boldFontWithSize:(CGFloat)size
{
    return [UIFont fontWithName:FOBoldFontName size:size];
}

+ (UIFont *)italicFontOfSize:(CGFloat)fontSize
{
    return [UIFont fontWithName:FOItalicFontName size:fontSize];
}

- (id)initCustomWithCoder:(NSCoder *)aDecoder {
    BOOL result = [aDecoder containsValueForKey:@"UIFontDescriptor"];

    if (result) {
        UIFontDescriptor *descriptor = [aDecoder decodeObjectForKey:@"UIFontDescriptor"];

        NSString *fontName;
        if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontRegularUsage"]) {
            fontName = FORegularFontName;
        }
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontEmphasizedUsage"]) {
            fontName = FOBoldFontName;
        }
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontObliqueUsage"]) {
            fontName = FOItalicFontName;
        }
        else {
            fontName = descriptor.fontAttributes[@"NSFontNameAttribute"];
        }

        return [UIFont fontWithName:fontName size:descriptor.pointSize];
    }

    self = [self initCustomWithCoder:aDecoder];

    return self;
}

+ (void)load
{
    [self replaceClassSelector:@selector(systemFontOfSize:) withSelector:@selector(regularFontWithSize:)];
    [self replaceClassSelector:@selector(boldSystemFontOfSize:) withSelector:@selector(boldFontWithSize:)];
    [self replaceClassSelector:@selector(italicSystemFontOfSize:) withSelector:@selector(italicFontOfSize:)];

    [self replaceInstanceSelector:@selector(initWithCoder:) withSelector:@selector(initCustomWithCoder:)];
}
#pragma clang diagnostic pop

@end

Як ви користуєтеся цією реалізацією на iOS6, у якої немає UIFontDescriptor
Utku Yıldırım

Я використовував ключ декодера "UIFontTraits", щоб перевірити, чи надається шрифт жирним або курсивом, і замінити його на мої власні варіанти. Отримав це з цієї суті тут gist.github.com/Daij-Djan/5046612 .
Фабіо Олівейра

Дякую за відповідь, я зараз використовував інше рішення. Я перевірю це, коли мені це буде потрібно ще раз :)
Utku Yıldırım

2
дякую @ FábioOliveira, це працює як шарм! Ще одне, що вам потрібно поставити #import <objc / runtime.h> на заголовок, інакше ви отримаєте помилку, скориставшись класом 'Method' (помилка, яку я отримую в XCode 6)
nahung89

Чомусь в iOS 8 модалі ( UIAlertController) не змінюють шрифт.
Randomblue

13

Щоб завершити відповідь Сенді Чапмен , ось рішення в Objective-C (поставте цю категорію в будь-якому місці, яке ви хочете змінити UILabel Appearance):

@implementation UILabel (FontOverride)
- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR {
    self.font = [UIFont fontWithName:name size:self.font.pointSize];
}
@end

Файл інтерфейсу має бути оголошений публічно для цього способу, щоб він пізніше використовувався в таких місцях, як делегат програми:

@interface UILabel (FontOverride)
  - (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR;
@end

Потім ви можете змінити за Appearanceдопомогою:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];

1
Привіт, ти маєш на увазі "де завгодно", що цей код потрібно було б додати до кожного контролера перегляду, а чи всі UILabel використовуються в контролері, де ви хотіли змінити шрифт?
Жуль

Ні, цей код потрібно вводити один раз у будь-якому місці вашого проекту; Наприклад, у вашому додатку до програми.
Демієн Дебін

1
@DamienDebin Я хочу використовувати жирний шрифт для жирного, але це змінюється жирним на світлий. Будь-який шлях?
Зеешан

Насправді це працює, але чи має бути це "Категорія" чи "Розширення"? Різниця пояснюється тут: stackoverflow.com/questions/7136124 / ...
Дарій Miliauskas

4

КОМЕНТАРИ ДЛЯ SWIFT 3.0 І ПОВЕРХНЕННЯ SWIFT

Ви можете видалити попереджувальне повідомлення в рядку:

let initCoderMethod = class_getInstanceMethod(self, Selector("initWithCoder:"))

Замінивши його на:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))

Лол. Я не знав, що Свіфт дозволяє це використовувати. До речі, я оновлю це до відповіді вище. Дякую @ucotta!
nahung89

4

Для Swift 5

Усі вищезазначені відповіді правильні, але я це зробив трохи по-іншому, відповідно до розміру пристрою . Тут, у класі ATFontManager, я зробив розмір шрифту за замовчуванням, який визначається у верхній частині класу як defaultFontSize , це розмір шрифту iphone plus і ви можете змінити відповідно до вашої вимоги.

class ATFontManager: UIFont{
    
    class func setFont( _ iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.helveticaNeue) -> UIFont{
        
        let defaultFontSize : CGFloat = 16
        
        switch ATDeviceDetector().screenType {
            
        case .iPhone4:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 5)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 5)!
            
        case .iPhone5:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 3)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 3)!
            
        case .iPhone6AndIphone7, .iPhoneUnknownSmallSize:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 2)!
            
        case .iPhone6PAndIPhone7P, .iPhoneUnknownBigSize:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
        case .iPhoneX, .iPhoneXsMax:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
          
        case .iPadMini:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadPro10Inch:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 4)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        case .iPadPro:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 6)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 6)!
            
        case .iPadUnknownSmallSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadUnknownBigSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        default:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 16)!
        }
    }
}
     

Я додав певну назву шрифту, для більшого розміру ви можете додати тут ім'я та тип шрифту.

   enum FontName : String {
        case HelveticaNeue = "HelveticaNeue"
        case HelveticaNeueUltraLight = "HelveticaNeue-UltraLight"
        case HelveticaNeueBold = "HelveticaNeue-Bold"
        case HelveticaNeueBoldItalic = "HelveticaNeue-BoldItalic"
        case HelveticaNeueMedium = "HelveticaNeue-Medium"
        case AvenirBlack = "Avenir-Black"
        case ArialBoldMT = "Arial-BoldMT"
        case HoeflerTextBlack = "HoeflerText-Black"
        case AMCAPEternal = "AMCAPEternal"
    }

Цей клас відноситься до детектора пристроїв, щоб забезпечити відповідний розмір шрифту відповідно до пристрою.

class ATDeviceDetector {
    
    var iPhone: Bool {
        
        return UIDevice().userInterfaceIdiom == .phone
    }
    
    var ipad : Bool{
        
        return UIDevice().userInterfaceIdiom == .pad
    }
    
    let isRetina = UIScreen.main.scale >= 2.0
    
    
    enum ScreenType: String {
        
        case iPhone4
        case iPhone5
        case iPhone6AndIphone7
        case iPhone6PAndIPhone7P
        case iPhoneX
        
        case iPadMini
        case iPadPro
        case iPadPro10Inch
        
        case iPhoneOrIPadSmallSizeUnknown
        case iPadUnknown
        case unknown
    }
    
    
    struct ScreenSize{
        
        static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
        static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
        static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
        static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
    }
    
    
    var screenType: ScreenType {
        
        switch ScreenSize.SCREEN_MAX_LENGTH {
            
        case 0..<568.0:
            return .iPhone4
        case 568.0:
            return .iPhone5
        case 667.0:
            return .iPhone6AndIphone7
        case 736.0:
            return .iPhone6PAndIPhone7P
        case 812.0:
            return .iPhoneX
        case 568.0..<812.0:
            return .iPhoneOrIPadSmallSizeUnknown
        case 1112.0:
            return .iPadPro10Inch
        case 1024.0:
            return .iPadMini
        case 1366.0:
            return .iPadPro
        case 812.0..<1366.0:
            return .iPadUnknown
        default:
            return .unknown
        }
    }
}

Як використовувати. Сподіваюся, це допоможе.

//for default 
label.font = ATFontManager.setFont()

//if you want to provide as your demand. Here **iPhone7PlusFontSize** variable is denoted as font size for *iphone 7plus and iphone 6 plus*, and it **ATFontManager** class automatically handle.
label.font = ATFontManager.setFont(iPhone7PlusFontSize: 15, andFontName: FontName.HelveticaNeue.rawValue)

3

Жодне з цих рішень не працює універсально у всьому додатку. Одне, що мені вдалося допомогти керувати шрифтами в Xcode, - це відкриття дошки розкадрування як вихідного коду (клацання Control та натискання клавіші управління в файлі Навігатор файлів> "Відкрити як"> "Джерело"), а потім робити пошук і заміну.


3

Тип шрифту завжди слід встановлювати в коді та підказці / раскадровці.

Що стосується коду, подібно до того, як сказав Hugues BR , це робити в категорії може вирішити проблему.

Для кнопки / розгортки ми можемо методом Swizzling awakeFromNib змінити тип шрифту, оскільки елемент інтерфейсу від nib / storyboard завжди викликає його, перш ніж показувати на екрані.

Я думаю, ви знаєте аспекти . Це бібліотека для програмування AOP, заснована на методі Swizzling. Ми створюємо каталогі для UILabel, UIButton, UITextView для її реалізації.

UILabel:

#import "UILabel+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UILabel (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UILabel* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

UIButton:

#import "UIButton+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UIButton (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UIButton* instance = [aspectInfo instance];
        UILabel* label = instance.titleLabel;
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:label.font.pointSize];
        instance.titleLabel.font = font;
    }error:nil];
}

@end

UITextField:

#import "UITextField+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextField (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UITextField* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

UITextView:

#import "UITextView+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextView (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UITextView* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

Ось і все, ви можете змінити HelveticaNeue-light на макрос зі своїм іменем шрифту.


3

Я створив власне перетворення типографії для Swift 4 після перегляду кількох публікацій, він охоплює більшість випадків, таких як:

1-й Додайте шрифти до структури проекту та у файл .plist (з такою ж назвою):

<key>UIAppFonts</key>
<array>
    <string>Typo-Light.ttf</string>
    <string>Typo-Regular.ttf</string>
    <string>Typo-Semibold.ttf</string>
    <string>Typo-LightItalic.ttf</string>
</array>

Тоді

struct Resources {

    struct Fonts {
        //struct is extended in Fonts
    }
}

extension Resources.Fonts {

    enum Weight: String {
        case light = "Typo-Light"
        case regular = "Typo-Regular"
        case semibold = "Typo-Semibold"
        case italic = "Typo-LightItalic"
    }
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {

    @objc class func mySystemFont(ofSize: CGFloat, weight: UIFont.Weight) -> UIFont {
        switch weight {
        case .semibold, .bold, .heavy, .black:
            return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: ofSize)!

        case .medium, .regular:
            return UIFont(name: Resources.Fonts.Weight.regular.rawValue, size: ofSize)!

        default:
            return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: ofSize)!
        }
    }

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.italic.rawValue, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {
        case "CTFontRegularUsage", "CTFontMediumUsage":
            fontName = Resources.Fonts.Weight.regular.rawValue
        case "CTFontEmphasizedUsage", "CTFontBoldUsage", "CTFontSemiboldUsage","CTFontHeavyUsage", "CTFontBlackUsage":
            fontName = Resources.Fonts.Weight.semibold.rawValue
        case "CTFontObliqueUsage":
            fontName = Resources.Fonts.Weight.italic.rawValue
        default:
            fontName = Resources.Fonts.Weight.light.rawValue
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }

    class func overrideDefaultTypography() {
        guard self == UIFont.self else { return }

        if let systemFontMethodWithWeight = class_getClassMethod(self, #selector(systemFont(ofSize: weight:))),
            let mySystemFontMethodWithWeight = class_getClassMethod(self, #selector(mySystemFont(ofSize: weight:))) {
            method_exchangeImplementations(systemFontMethodWithWeight, mySystemFontMethodWithWeight)
        }

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))),
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        }
    }
}

Нарешті зателефонуйте до створеного методу Appdelegateяк наступний:

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        UIFont.overrideDefaultTypography()
        return true
    }
}

@sheshnath Ви можете дати нам більше інформації про аварійне завершення роботи?
Хав'єр Амор

1
Вибачте, помилка була з мого боку, шрифт не вказаний у info.plist
shesh

@midhunp Чи можете ви бути більш чіткими, щоб він не працював для вас? Це добре працює для мене з жирним шрифтом.
Хав'єр Амор

2

Напевно, ні, ви, ймовірно, самі встановите шрифт на своєму керуванні, але ви можете полегшити процес, централізуючи, де ви отримуєте типи шрифтів, наприклад, у делегата програми або у якогось іншого загального класу є метод, який повертає шрифт, і все, що потрібно для встановлення шрифту, може викликати цей метод, який допоможе у випадку, якщо вам потрібно змінити свій шрифт, змінити його в одному місці, а не скрізь, де ви встановлюєте шрифти ... Іншою альтернативою може бути створення підкласів ваші елементи інтерфейсу, які автоматично встановлять шрифт, але це може бути зайвим.


для запису, це я і зробив, але @Randall потребував представника, і він дав хорошу відповідь. Мені просто потрібно підтримувати менше 5,0
Сем Джарман

4
Я не згоден з тим, що ти зробив. Вибрана відповідь не вірна, якщо ваше питання позначено тегом iphone-sdk-4.0.
Пауло Касаретто

@Sam Jarman, відповідь Рендала нижче правильна - чи можете ви позначити це таким чином для майбутніх відвідувачів?
Білл

1

NUI - це альтернатива проксі-серверу UIAppearance. Він надає вам контроль над шрифтом (та багатьма іншими атрибутами) великої кількості типів елементів інтерфейсу у всій програмі, просто модифікувавши таблицю стилів, яку можна повторно використовувати у кількох програмах.

Після додавання NUILabelкласу до міток ви можете легко керувати їх шрифтом у таблиці стилів:

LabelFontName    String    Helvetica

Якщо у вас є мітки з різними розмірами шрифту, ви можете контролювати їх розміри, використовуючи класи NUI Label, LargeLabel і SmallLabel, або навіть швидко створювати власні класи.


1

Я швидко використовую подібний тип класу шрифтів. Використання класу розширення шрифту.

enum FontName: String {

  case regular      = "Roboto-Regular"

}

//MARK: - Set Font Size
enum FontSize: CGFloat {
    case size = 10

}
extension UIFont {

    //MARK: - Bold Font
  class var regularFont10: UIFont {
        return UIFont(name: FontName.regular.rawValue, size:FontSize.size.rawValue )!
    }
}

0

Для коду Xamarin.iOS всередині AppDelegate FinishedLaunching()ставиться такий: -

UILabel.Appearance.Font= UIFont.FromName("Lato-Regular", 14);

встановіть шрифт для всієї програми та додайте UIAppFontsклавішу ' ' в Info.plist, шлях повинен бути шлях, де знаходиться ваш файл шрифту .ttf. Для мене це було у папці 'шрифти' в моєму проекті.

<key>UIAppFonts</key>
    <array>
        <string>fonts/Lato-Regular.ttf</string>
    </array>

0

Як @Randall згадав UIApperanceпроксі iOS 5.0+, можна налаштувати зовнішній вигляд усіх екземплярів класу читати докладніше .

Автоматичне завершення Xcodes не відображає всіх доступних властивостей і може призвести до помилки, але ви можете просто ввести його, і воно буде компілюватися.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)

-1

Те саме ми досягли у Swift -Xcode 7.2 за допомогою контролера батьківського перегляду та контролера дочірнього перегляду (спадкування).

Файл - Новий - Какао сенсорний клас - ParentViewController.

    import UIKit
    import Foundation

    class ParentViewController: UIViewController {

        var appUIColor:UIColor = UIColor.redColor()
        var appFont:UIFont = UIFont(name: "Copperplate", size: 20)!

        override func viewDidLoad() {
            super.viewDidLoad()
        }
        func addStatusBar()
        {
            let view = UIView(frame:
                CGRect(x: 0.0, y: 0.0, width: UIScreen.mainScreen().bounds.size.width, height: 20.0)
            )
            view.backgroundColor = appUIColor
            self.view.addSubview(view)
        }
    }    

Створіть контролери перегляду дітей і зв’яжіть його з VC StoryBoard, додайте textLabel.

    import UIKit

    class FontTestController: ParentViewController {
        @IBOutlet var testLabel: UILabel!

        override func viewDidLoad() {
            super.viewDidLoad()
            testLabel.font =  appFont
            testLabel.textColor = appUIColor
        }

АБО Створіть спеціальний клас UILabel (метод підкласифікації) та додайте до нього потрібні мітки.

import Foundation
import UIKit

class CustomFontLabel: UILabel {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        backgroundColor = ParentViewController().appUIColor
        font = ParentViewController().appFont
        textColor = UIColor.blackColor()
    }
}

Примітка: Шрифт та колір, оголошені в Parent VC, реалізовані в CustomFontLabel. Перевага полягає в тому, що ми можемо змінити властивості uilabel / будь-якого перегляду всі разом у кількох простих змінах у батьківському ЦК.

2) "для", циклічне використання UIView для додаткових подань. Він працює лише на певному ВК.

    override func viewWillLayoutSubviews() {
            for view in self.view.subviews  {
                if view.isKindOfClass(UITextField) {
                UITextField.appearance().font =  UIFont(name: "Copperplate", size: 20)
                }
                if view.isKindOfClass(UILabel) {
                    UILabel.appearance().font =  UIFont(name: "Copperplate", size: 20)    
                }               
            }       
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.