Установить шрифт по умолчанию для всего приложения iOS?

155

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

Есть ли способ установить шрифт по умолчанию (ярлыки по умолчанию используют SystemFont) для всего приложения?

Сэм Джарман
источник
7
Огромный взгляд на это горе. Мы честно нашли, что самое простое, что нужно сделать, это просто создать (тривиальный) новый класс для каждого элемента управления. Так что для UIButton сделайте SJButton. Не забудьте переопределить initWithFrame и initWithCode. Для каждого элемента управления (скажем, UIButton и т. Д.) Установите цвета или все, что вам нравится. Тщательно подберите, скажем, размер (т. Е. Это будет размер, установленный на табло) в коде int, а затем (как вы предпочитаете) используйте этот размер (и установите, скажем, шрифт, цвет - как угодно). Это всего лишь несколько строк кода, он невероятно аккуратен и экономит ваше время в долгосрочной перспективе.
Толстяк
@JoeBlow Спасибо за публикацию ваших результатов - собирался потратить время на поиски ответа на этот вопрос сам
jj.
@ jj- Верно. Не забывайте, что вы, безусловно, должны использовать в IBDesignableэти дни. Надеюсь, поможет. Также рассмотрим этот интересный QA: stackoverflow.com/a/38000466/294884
Толстяк

Ответы:

158

Кажется, это возможно в iOS 5 с использованием прокси-сервера UIAppearance.

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

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

Помните, что вам нужно поместить значение UIAppFonts в ваш info.plist и включить имя шрифта, который вы включаете.

Randall
источник
46
Спасибо за ответ. Я смог заставить это работать. Знаете ли вы, есть ли способ указать шрифт без указания размера шрифта? В моем приложении есть ярлыки, которые не имеют одинаковый размер шрифта.
Брэндон
23
Могу ли я сделать это без переопределения размера точки каждого экземпляра?
Майкл Форрест
17
setFont:метод устарел
Ананд
12
@ А ты уверен в этом? Я не вижу его помеченным как устаревший в UILabel. Он устарел, UIButtonно titleLabelвместо него используется шрифт для свойства, которое является UILabel, так что просто установить шрифт с помощью прокси-сервера для появления UILabelдолжно быть хорошо.
Адриан Шениг
6
@ И это не рекомендуется для UILabel.
Аластер Стюарт
118

Swift 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()
    }
    ...
}
nahung89
источник
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.

Hugues BR
источник
1
Это в пределах руководящих принципов яблока?
Рамбатино
Это больше взломать. Я не добавил свой реестр приложений с этим хаком, так как он не использует никаких частных методов. Если вы хотите более надежное решение, я также предлагаю вам проверить это: github.com/0xced/FontReplacer
Hugues BR
2
Это отлично. Apple просто не хочет, чтобы вы использовали недокументированные функции. Вам разрешено публично публиковать методы.
mxcl
4
Когда у категории есть методы с такой же сигнатурой, что и у класса, расширение ее поведения не определено. Чтобы заменить методы класса, вы должны использовать метод swizzling (что тоже не очень хорошая идея).
GreatWiz
1
Как уже отмечали другие, это решение, хотя и может быть эффективным в большинстве случаев, технически представляет потенциал для неопределенного поведения. Если вы не хотите рисковать, лучше использовать метод Swizzling. Ответ здесь дает то же решение через Swizzling: stackoverflow.com/questions/19542942/…
Натан Хосселтон
64

Если вы используете 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)
            }
        }
    }
}

Тогда для ваших прокси UIAppearance:

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. Так что поиск «Bold» никогда не подходил ни к чему. Я изменил это на rangeOfString("Medium")и это сработало.
Мейсон Дж. Жвити
23

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

Подход с динамическим типом должен быть тем, что вы должны искать в iOS 7. Следующее решение не использует динамический тип.


Ноты:

  • приведенный ниже код в представленном виде никогда не был одобрен 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/…
Дариус Милиаускас
4

КОММЕНТАРИЙ ДЛЯ SWIFT 3.0 И ПРЕДУПРЕЖДЕНИЕ SWIFT

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

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

Заменив его на:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))
ucotta
источник
Ржунимагу. Я не знал, что Свифт разрешит использовать это. Кстати, я буду обновлять его выше ответ. Спасибо тебе @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» в «Навигаторе файлов»> «Открыть как»> «Исходный код»), а затем выполнить поиск и замену.

Gingi
источник
3

Тип шрифта всегда задается в коде и перо / раскадровка.

Для кода, как сказал Hugues BR , сделать это в категориях может решить проблему.

Для пера / раскадровки мы можем использовать метод Swizzling awakeFromNib, чтобы изменить тип шрифта, поскольку элемент пользовательского интерфейса из пера / раскадровки всегда вызывает его перед отображением на экране.

Я полагаю, вы знаете Аспекты . Это библиотека для программирования АОП, основанная на методе 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
nath
@midhunp Не могли бы вы быть более явным, чтобы он не работал для вас ?. Это хорошо работает для меня с жирным шрифтом.
Хавьер Амор Пенас
2

Вероятно, нет, вы, вероятно, будете сами устанавливать шрифт на своем элементе управления, но вы можете упростить процесс, централизовав, откуда вы получаете типы шрифтов, например, у делегата приложения или в каком-либо другом общем классе есть метод, который возвращает шрифт и все, что нужно для установки шрифта, может вызывать этот метод, который поможет в случае, если вам нужно изменить ваш шрифт, вы будете менять его в одном месте, а не везде, где вы устанавливаете шрифты ... Другой альтернативой может быть создание подклассов ваши элементы пользовательского интерфейса, которые будут автоматически устанавливать шрифт, но это может быть излишним ..

Даниил
источник
для протокола, это то, что я сделал, но @Randall нуждался в представителе и дал хороший ответ. Мне просто нужно поддерживать менее 5,0
Сэм Джарман
4
Я не согласен с тем, что ты сделал. Выбранный вами ответ недействителен, если ваш вопрос помечен как iphone-sdk-4.0.
Пауло Касаретто
@ Сэм Джарман, ответ Рэндалла ниже верен - можете ли вы отметить его таким образом для будущих посетителей?
Билл
1

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

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

LabelFontName    String    Helvetica

Если у вас есть ярлыки с разными размерами шрифта, вы можете контролировать их размеры с помощью классов Label, LargeLabel и SmallLabel в NUI или даже быстро создавать свои собственные классы.

Том
источник
1

Использую как этот тип шрифта класса в Swift. Использование класса расширения шрифта.

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 )!
    }
}
Karthickkck
источник
0

Для Xamarin.iOS внутри FinishedLaunching()положенного кода AppDelegate, например:

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

установить шрифт для всего приложения и добавить « UIAppFonts» в Info.plist, путь должен быть путем, где находится ваш файл шрифта .ttf. Для меня это было внутри папки «шрифты» в моем проекте.

<key>UIAppFonts</key>
    <array>
        <string>fonts/Lato-Regular.ttf</string>
    </array>
Annu
источник
0

Как уже упоминалось @Randall IOS 5.0 и старше UIApperanceпрокси может быть использован для настройки внешнего вида всех экземпляров класса читать далее .

Xcodes auto complete не отображает все доступные свойства и может выдать ошибку, но вы можете просто напечатать ее, и она скомпилируется.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)
esesmuedgars
источник
-1

Мы достигли того же в Swift -Xcode 7.2, используя Parent View Controller и Child view controller (Наследование).

Файл - Новый - Класс Touch Какао - 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)
        }
    }    

Сделайте дочерние контроллеры представления и свяжитесь с StoryBoard VC, добавьте 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 / любого представления вместе в некоторых простых изменениях в Parent VC.

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)    
                }               
            }       
        }
AG
источник