Tetapkan font default untuk seluruh aplikasi iOS?

155

Saya memiliki font khusus yang ingin saya gunakan untuk semua yang menampilkan teks di aplikasi, label, tampilan teks, dll.

Apakah ada cara untuk mengatur font default (label secara default menggunakan SystemFont) untuk seluruh aplikasi?

Sam Jarman
sumber
7
Setelah secara masif melihat ke dalam celaka ini. Kami telah jujur ​​menemukan hal paling sederhana untuk dilakukan adalah hanya membuat kelas baru (sepele), untuk setiap kontrol. Jadi untuk UIButton, buat SJButton. Jangan lupa untuk mengganti initWithFrame dan initWithCode. Untuk setiap kontrol (katakanlah UIButton, dll.) Atur warna atau apa pun yang Anda suka. Ambil dengan hati-hati katakan ukurannya (yaitu ukuran yang akan SET DI STORYBOARD) dalam kode int, dan kemudian (seperti yang Anda inginkan) gunakan ukuran itu (dan atur, katakanlah, font, warna - apa pun). Itu hanya beberapa baris kode, sangat rapi, dan menghemat waktu Anda dalam jangka panjang.
Fattie
@ JoBlow Terima kasih telah memposting temuan Anda - hampir menghabiskan waktu mencari jawaban sendiri
jj.
@ jj- Benar. Jangan lupa kamu pasti HARUS menggunakannya IBDesignablehari ini. Semoga ini bisa membantu. Juga pertimbangkan QA yang menarik ini: stackoverflow.com/a/38000466/294884
Fattie

Jawaban:

158

Tampaknya dimungkinkan di iOS 5 menggunakan proxy UIAppearance.

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

Itu akan mengatur font menjadi apa pun font khusus Anda untuk semua UILabel di aplikasi Anda. Anda harus mengulanginya untuk setiap kontrol (UIButton, UILabel, dll.).

Ingat Anda harus memasukkan nilai UIAppFonts di info Anda. Daftar dan sertakan nama font yang Anda masukkan.

Randall
sumber
46
Terima kasih atas tanggapannya. Saya bisa membuatnya bekerja. Apakah Anda tahu jika ada cara untuk menentukan font tanpa menentukan ukuran font? Saya memiliki label di aplikasi saya yang tidak memiliki ukuran font yang sama.
Brandon
23
Bisakah saya melakukan ini tanpa mengesampingkan ukuran titik setiap instance?
Michael Forrest
17
setFont:metode sudah usang
Anand
12
@ Dan apakah Anda yakin tentang ini? Saya tidak melihatnya ditandai sebagai usang UILabel. Itu sudah usang UIButtontetapi menggunakan font untuk titleLabelproperti sebagai gantinya UILabel, jadi hanya mengatur font dengan proxy penampilan UILabelharus baik-baik saja.
Adrian Schönig
6
@ Dan itu tidak ditinggalkan untuk UILabel.
Alastair Stuart
118

Cepat 5

Berdasarkan jawaban Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ), saya membuat swift saya sendiri 4.

Singkatnya, ini fungsi pertukaran ekstensi standar init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:), italicSystemFont(ofSize:)dengan metode kebiasaan saya.

Perhatikan bahwa itu tidak sepenuhnya diterapkan, tetapi Anda dapat bertukar lebih banyak metode berdasarkan implementasi saya.

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
sumber
2
jawaban Terbaik!! secara otomatis mengganti font sistem, brilian
Kappe
2
Jika seseorang memiliki masalah dengan baris "NSCTFontUIUsageAttribute": if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {lakukan trik untuk saya.
Pengetahuan
1
tampaknya tidak berfungsi dengan UILabels yang mengatur gaya teks (tebal, judul, judul, dll.) ... hanya berfungsi dengan font yang memiliki ukuran dan set font sistem tertentu. @ nahung89
aviran
1
Ini juga mengganti beberapa font UI sistem. Misalnya, daftar saran keyboard dan lembar tindakan. Tidak tahu apakah ini akan menyebabkan Apple menolak aplikasi
Henry H Miao
1
Sudah setahun sejak jawaban ini diposting. Adakah yang punya cara Apple "asli" untuk mencapai ini?
Greg Hilston
75

Ada juga solusi lain yang akan menggantikan systemFont.

Cukup buat kategori

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

Ini akan menggantikan implementasi default dan sebagian besar UIControls menggunakan systemFont.

Hugues BR
sumber
1
Apakah ini sesuai dengan pedoman apel?
Rambatino
Ini lebih merupakan peretasan. Saya belum menambahkan daftar aplikasi saya dengan peretasan ini, karena tidak menggunakan metode pribadi. Jika Anda menginginkan solusi yang lebih kuat, saya juga menyarankan Anda untuk memeriksa ini: github.com/0xced/FontReplacer
Hugues BR
2
Ini baik Apple hanya tidak ingin Anda menggunakan fungsi tidak berdokumen. Anda diizinkan untuk "memutar" metode yang bersifat publik.
mxcl
4
Ketika suatu kategori memiliki metode dengan tanda tangan yang sama dengan kelas itu memperluas perilaku tidak terdefinisi. Untuk mengganti metode kelas, Anda harus menggunakan metode swizzling (yang juga bukan ide yang baik).
GreatWiz
1
Seperti yang telah ditunjukkan oleh orang lain, solusi ini, walaupun kemungkinan besar akan efektif sebagian besar waktu, secara teknis memperkenalkan potensi perilaku yang tidak terdefinisi. Jika Anda tidak ingin mengambil risiko, metode swizzling mungkin merupakan pilihan yang lebih baik. Jawabannya di sini memberikan solusi yang sama melalui swizzling: stackoverflow.com/questions/19542942/…
Nathan Hosselton
64

Jika Anda menggunakan Swift, Anda dapat membuat ekstensi UILabel:

extension UILabel {

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

}

Dan kemudian di mana Anda melakukan proksi penampilan Anda:

UILabel.appearance().substituteFontName = applicationFont

Ada kode Objective-C setara menggunakan UI_APPEARANCE_SELECTORpada properti dengan nama substituteFontName.

Tambahan

Untuk kasus di mana Anda ingin mengatur font tebal dan reguler secara terpisah:

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)
            }
        }
    }
}

Kemudian untuk proksi penampilan UIA Anda:

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

Catatan: jika Anda menemukan bahwa subtitle tebal tidak berfungsi, mungkin nama font default tidak mengandung "Medium". Ganti string itu untuk pertandingan lain sesuai kebutuhan (terima kasih kepada Mason dalam komentar di bawah).

Sandy Chapman
sumber
Satu kelemahan dari ini yang saya temukan adalah ketika saya memulai peringatan dengan UIAlertController, tombol dengan gaya .Cancel sama dengan tombol dengan gaya .Default (setidaknya saat menggunakan GillSans). Sedangkan .Cancel biasanya merupakan font berat reguler, dan .Default akan dicetak tebal. Ada ide?
Mason G. Zhwiti
Maaf, maksud saya label .Cancel biasanya akan tebal, dan Default biasanya akan menjadi berat reguler.
Mason G. Zhwiti
2
@ MasonG.Zhwiti Dalam hal ini, saya mungkin akan mengatur UILabelekstensi untuk mengambil nama font tambahan untuk dicetak tebal. Kemudian di setlakukan pemeriksaan untuk melihat apakah "Bold" ada dalam nama font dan abaikan set di satu kasus, dan gunakan di yang lain. Saya akan mengedit dan menambahkan contoh.
Sandy Chapman
@SandyChapman Terima kasih! Saya mencoba teknik baru ini, dan itu masuk akal, tetapi sepertinya itu tidak berhasil bagi saya. Saya menggunakan GillSans dan GillSans-Bold pada simulator iOS 8.3. Sudahkah Anda menguji teknik ini?
Mason G. Zhwiti
2
@SandyChapman Saya tahu apa yang terjadi. Font default untuk iOS 8 cenderung HelveticaNeueInterface-Regular atau (untuk huruf tebal) HelveticaNeueInterface-MediumP4. Jadi mencari "Bold" tidak pernah cocok dengan apa pun. Saya mengubahnya menjadi rangeOfString("Medium")dan berhasil.
Mason G. Zhwiti
23

Berkembang dari Hugues, BR menjawab tetapi dengan menggunakan metode swizzling, saya tiba pada solusi yang berhasil mengubah semua font menjadi font yang diinginkan di aplikasi saya.

Pendekatan dengan Dynamic Type harus seperti yang Anda cari di iOS 7. Solusi berikut ini tidak menggunakan Dynamic Type.


Catatan:

  • kode di bawah ini, dalam kondisi yang disajikan, tidak pernah diajukan kepada Apple;
  • ada versi yang lebih pendek yang melewati pengajuan Apple, yaitu tanpa - initWithCoder:penggantian. Namun itu tidak akan mencakup semua kasus;
  • kode berikut hadir dalam kelas yang saya gunakan untuk mengatur gaya aplikasi saya yang disertakan oleh kelas AppDelegate saya sehingga tersedia di mana-mana dan untuk semua instance UIFont;
  • Saya menggunakan Zapfino di sini hanya untuk membuat perubahan lebih terlihat;
  • setiap perbaikan yang Anda temukan pada kode ini dipersilahkan.

Solusi ini menggunakan dua metode berbeda untuk mencapai hasil akhir. Yang pertama adalah mengganti metode kelas UIFont + systemFontWithSize:dan mirip dengan yang menggunakan alternatif saya (di sini saya menggunakan "Zapfino" untuk tidak meninggalkan keraguan bahwa penggantian berhasil).

Metode lainnya adalah mengganti - initWithCoder:metode pada UIFont untuk menggantikan kemunculan CTFontRegularUsagedan serupa dengan alternatif saya. Metode terakhir ini diperlukan karena saya telah menemukan bahwa UILabelobjek yang dikodekan dalam file NIB tidak memeriksa + systemFontWithSize:metode untuk mendapatkan font sistem mereka dan sebaliknya mengkodekan mereka sebagai UICTFontDescriptorobjek. Saya sudah mencoba menimpa - awakeAfterUsingCoder:tetapi entah bagaimana ia dipanggil untuk setiap objek yang disandikan di storyboard saya dan menyebabkan crash. Mengganti - awakeFromNibtidak akan mengizinkan saya membaca NSCoderobjek.

#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
Fábio Oliveira
sumber
Bagaimana Anda menggunakan implementasi ini di iOS6 yang tidak memiliki UIFontDescriptor
Utku Yıldırım
Saya telah menggunakan kunci dekoder "UIFontTraits" untuk memeriksa apakah font yang diberikan tebal atau miring dan ganti dengan variasi saya sendiri. Dapatkan dari intisari ini di sini gist.github.com/Daij-Djan/5046612 .
Fábio Oliveira
Terima kasih atas jawaban saya menggunakan solusi lain untuk saat ini. Saya akan memeriksanya ketika saya membutuhkannya lagi :)
Utku Yıldırım
2
terima kasih @ FábioOliveira, ini bekerja seperti pesona! Hanya satu hal lagi yang perlu Anda letakkan #import <objc / runtime.h> di header, jika tidak, Anda akan mendapatkan kesalahan dengan menggunakan kelas 'Metode' (kesalahan yang saya dapatkan di
XCode
Untuk beberapa alasan, di iOS 8, modals ( UIAlertController) tidak mengubah font.
Randomblue
13

Untuk melengkapi jawaban Sandy Chapman , berikut adalah solusi di Objective-C (letakkan kategori ini di mana saja yang ingin Anda ubah UILabel Appearance):

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

File antarmuka, harusnya menyatakan metode ini secara publik untuk digunakan nanti dari tempat-tempat seperti delegasi aplikasi Anda:

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

Kemudian, Anda dapat mengubah Appearancedengan:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];
Damien Debin
sumber
1
Hai, maksud Anda "di mana saja", kode itu harus ditambahkan di setiap view controller, dan apakah setiap UILabel digunakan di controller, di mana Anda ingin mengubah font?
Jules
Tidak, Anda harus meletakkan kode ini sekali , di mana saja dalam proyek Anda; di delegasi app Anda misalnya.
Damien Debin
1
@ DamenDebin Saya ingin menggunakan huruf tebal untuk huruf tebal tetapi ini berubah menjadi tebal. Ada jalan lain?
Zeeshan
Sebenarnya, itu berfungsi, tetapi haruskah itu "Kategori" atau "Extention"? Perbedaannya dijelaskan di sini: stackoverflow.com/questions/7136124/…
Darius Miliauskas
4

KOMENTAR UNTUK SWIFT 3.0 DAN SWIFT WARNING

Anda dapat menghapus pesan peringatan di baris:

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

Dengan menggantinya dengan:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))
ucotta
sumber
Lol. Saya tidak tahu bahwa Swift mengizinkan menggunakan ini. Btw, saya akan memperbarui ke jawaban di atas. @Ucotta terima kasih!
nahung89
4

Untuk Swift 5

Semua jawaban di atas sudah benar tetapi saya telah melakukan dengan sedikit cara berbeda yang sesuai dengan ukuran perangkat . Di sini, di kelas ATFontManager, saya telah membuat ukuran font default yang didefinisikan di bagian atas kelas sebagai defaultFontSize , ini adalah ukuran font iphone plus dan Anda dapat mengubah sesuai dengan kebutuhan Anda.

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)!
        }
    }
}
     

Saya telah menambahkan nama font tertentu, untuk lebih Anda bisa menambahkan nama font dan ketik di sini.

   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"
    }

Kelas ini mengacu pada detektor perangkat untuk memberikan ukuran font yang sesuai menurut perangkat.

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

Cara Penggunaan. Semoga ini bisa membantu.

//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)
Amrit Tiwari
sumber
3

Tak satu pun dari solusi ini bekerja secara universal di seluruh aplikasi. Satu hal yang saya temukan untuk membantu mengelola font di Xcode adalah membuka Storyboard sebagai kode Sumber (Control-klik storyboard di File navigator> "Open as"> "Source"), dan kemudian melakukan pencarian-dan-ganti.

Gingi
sumber
3

Jenis font selalu diatur dalam kode dan nib / storyboard.

Untuk kodenya, seperti kata Hugues BR , melakukannya dalam kategori dapat memecahkan masalah.

Untuk nib / storyboard, kita dapat Method Swizzling awakeFromNib untuk mengubah jenis font karena elemen UI dari nib / storyboard selalu memanggilnya sebelum ditampilkan di layar.

Saya kira Anda tahu Aspek . Ini adalah perpustakaan untuk pemrograman AOP, berdasarkan Metode Swizzling. Kami membuat kategori untuk UILabel, UIButton, UITextView untuk mengimplementasikannya.

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

Itu saja, Anda bisa mengubah HelveticaNeue-light menjadi makro dengan nama font Anda.

Peng Xiaofeng
sumber
3

Saya membuat konversi tipografi saya sendiri untuk Swift 4 setelah meninjau beberapa posting, mencakup sebagian besar kasus, seperti:

1st Tambahkan font ke proyek estructure dan ke file .plist (dengan nama yang sama):

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

Kemudian

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)
        }
    }
}

Akhirnya panggil ke metode yang dibuat di Appdelegateseperti berikut:

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

        UIFont.overrideDefaultTypography()
        return true
    }
}
Javier Amor Penas
sumber
@sheshnath dapatkah Anda memberi kami lebih banyak info kerusakan?
Javier Amor Penas
1
maaf kesalahan adalah dari sisi saya, font tidak terdaftar di info.plist
shesh nath
@ midhunp Bisakah Anda lebih eksplisit sehingga tidak bekerja untuk Anda? Ini bekerja dengan baik untuk saya dengan huruf tebal.
Javier Amor Penas
2

Mungkin tidak, Anda mungkin akan memiliki sendiri pengaturan font pada kontrol Anda, tetapi Anda dapat membuat proses lebih mudah dengan memusatkan dari mana Anda mendapatkan jenis font dari, misalnya memiliki delegasi aplikasi atau beberapa kelas umum lainnya memiliki metode yang mengembalikan font, dan apa pun yang perlu mengatur font dapat memanggil metode itu, yang akan membantu jika Anda perlu mengubah font Anda, Anda akan mengubahnya di satu tempat daripada di mana-mana Anda mengatur font ... Alternatif lain dapat membuat subclass dari Elemen UI Anda yang secara otomatis akan mengatur font, tapi itu mungkin berlebihan ..

Daniel
sumber
sebagai catatan, inilah yang saya lakukan, tetapi @Randall membutuhkan perwakilan, dan memberikan jawaban yang baik. Saya hanya perlu mendukung kurang dari 5,0
Sam Jarman
4
Saya tidak setuju dengan apa yang Anda lakukan. Jawaban yang Anda pilih tidak valid ketika pertanyaan Anda ditandai iphone-sdk-4.0.
Paulo Casaretto
@ Sam Jarman, jawaban Randall di bawah ini benar - dapatkah Anda menandainya seperti itu untuk pengunjung masa depan?
Bill
1

NUI adalah alternatif untuk proxy UIAppearance. Ini memberi Anda kontrol atas font (dan banyak atribut lainnya) dari sejumlah besar jenis elemen UI di seluruh aplikasi Anda dengan hanya memodifikasi lembar gaya, yang dapat digunakan kembali di beberapa aplikasi.

Setelah menambahkan NUILabelkelas ke label Anda, Anda dapat dengan mudah mengontrol font mereka di style sheet:

LabelFontName    String    Helvetica

Jika Anda memiliki label dengan ukuran font yang berbeda, Anda bisa mengontrol ukurannya menggunakan label NUI, LargeLabel, dan SmallLabel, atau bahkan dengan cepat membuat kelas Anda sendiri.

Tom
sumber
1

Saya menggunakan jenis kelas font seperti ini di swift. Menggunakan kelas ekstensi font.

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
sumber
0

Untuk Xamarin.iOS di dalam FinishedLaunching()kode put AppDelegate seperti ini: -

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

atur font untuk seluruh aplikasi dan Tambahkan UIAppFontskunci 'pada Info.plist, path harus jalur di mana file font Anda .ttf terletak. Bagi saya itu ada di dalam folder' font 'dalam proyek saya.

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

Seperti @Randall menyebutkan UIApperanceproxy iOS 5.0+ dapat digunakan untuk menyesuaikan tampilan semua instance kelas, baca lebih lanjut .

Xcodes auto complete tidak menampilkan semua properti yang tersedia dan mungkin membuat kesalahan, tetapi Anda bisa mengetiknya dan akan dikompilasi.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)
esesmuedgars
sumber
-1

Kami telah mencapai hal yang sama di Swift -Xcode 7.2 menggunakan Parent View Controller dan Child view controller (Inheritance).

File - Baru - kelas Cocoa 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)
        }
    }    

Buat pengontrol tampilan anak dan kaitkan dengan StoryBoard VC, tambahkan textLabel.

    import UIKit

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

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

ATAU Buat kelas UILabel khusus (Metode sub-klasifikasi) dan kaitkan label yang diperlukan untuk itu.

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()
    }
}

Catatan: Font dan warna yang dideklarasikan di Parent VC diimplementasikan di CustomFontLabel. Keuntungannya adalah kita dapat mengubah properti uilabel / sembarang tampilan secara bersamaan dalam beberapa perubahan sederhana di Parent VC.

2) 'untuk' pengulangan UIView untuk sub tampilan. Ini hanya berfungsi pada VC tertentu.

    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
sumber