ตั้งค่าฟอนต์เริ่มต้นสำหรับแอพ iOS ทั้งหมดหรือไม่


155

ฉันมีแบบอักษรที่กำหนดเองที่ฉันต้องการใช้สำหรับทุกสิ่งที่แสดงข้อความในแอพ, ป้ายกำกับ, การดูข้อความ ฯลฯ

มีวิธีการตั้งค่าแบบอักษรเริ่มต้น (ป้ายกำกับตามค่าเริ่มต้นใช้ SystemFont) สำหรับแอปทั้งหมดหรือไม่


7
ต้องมองเข้าไปในความฉิบหายอย่างหนาแน่น เราได้พบสิ่งที่ง่ายที่สุดในการทำอย่างตรงไปตรงมาก็แค่สร้างคลาสใหม่ (เล็กน้อย) สำหรับแต่ละการควบคุม ดังนั้นสำหรับ UIButton ให้สร้าง SJButton อย่าลืมลบล้างทั้ง initWithFrame และ initWithCode สำหรับแต่ละการควบคุม (เช่น UIButton ฯลฯ ) ตั้งค่าสีหรือสิ่งที่คุณต้องการ หยิบอย่างระมัดระวังพูดขนาด (เช่นที่จะเป็นขนาดที่ตั้งอยู่บนกระดานเรื่องราว) ในรหัส 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
ฉันสามารถทำได้โดยไม่ต้องเอาชนะขนาดพอยต์ของทุกอินสแตนซ์หรือไม่?
Michael Forrest

17
setFont:วิธีเลิกใช้แล้ว
Anand

12
@ คุณแน่ใจเกี่ยวกับสิ่งนี้หรือไม่? UILabelฉันไม่เห็นมันทำเครื่องหมายว่าเลิกใน มันเลิกใช้แล้วUIButtonแต่ใช้ฟอนต์สำหรับtitleLabelคุณสมบัติแทนซึ่งก็คือ a UILabelดังนั้นเพียงแค่ตั้งค่าฟอนต์ด้วย proxy proxy สำหรับUILabelควรจะดี
Adrian Schönig

6
@ และมันไม่ได้คัดค้านสำหรับ UILabel
Alastair Stuart

118

สวิฟท์ 5

จากคำตอบของFábio Oliveira ( 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
คำตอบที่ดีที่สุด !! แทนที่ฟอนต์ระบบโดยอัตโนมัติ, brilliant
Kappe

2
หากใครบางคนมีปัญหากับบรรทัด "NSCTFontUIUsageAttribute": if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {ทำเคล็ดลับสำหรับฉัน
ความรู้

1
ดูเหมือนจะไม่ทำงานกับUILabels ที่ตั้งค่ารูปแบบข้อความ (ตัวหนาพาดหัวหัวเรื่อง ฯลฯ ) ... ใช้ได้เฉพาะกับแบบอักษรที่มีขนาดที่กำหนดและชุดแบบอักษรของระบบ @ nahung89
aviran

1
นี่เป็นการสลับแบบอักษร UI ของระบบด้วย ตัวอย่างเช่นรายการแนะนำแป้นพิมพ์และแผ่นงาน ไม่ทราบว่าจะทำให้ Apple ปฏิเสธแอปนี้หรือไม่
Henry H Miao

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
สิ่งนี้อยู่ภายในแนวทางของแอปเปิ้ลหรือไม่?
Rambatino

มันแฮ็คมากกว่า ฉันยังไม่ได้เพิ่มแอพลงทะเบียนด้วยแฮ็คนี้เนื่องจากไม่ได้ใช้วิธีการส่วนตัว หากคุณต้องการโซลูชันที่มีประสิทธิภาพยิ่งขึ้นฉันขอแนะนำให้คุณตรวจสอบสิ่งนี้: github.com/0xced/FontReplacer
Hugues BR

2
นี่เป็นเรื่องปกติ Apple ไม่ต้องการให้คุณใช้ฟังก์ชั่นที่ไม่มีเอกสาร คุณได้รับอนุญาตให้ใช้วิธี "swizzle" ที่เป็นสาธารณะ
mxcl

4
เมื่อหมวดหมู่มีวิธีการที่มีลายเซ็นเดียวกันกับคลาสการขยายลักษณะการทำงานนั้นไม่ได้กำหนดไว้ ในการแทนที่วิธีการเรียนคุณควรใช้วิธีการแบบ swizzling (ซึ่งไม่ใช่ความคิดที่ดี)
GreatWiz

1
ดังที่คนอื่น ๆ ได้ชี้ให้เห็นวิธีแก้ปัญหานี้ในขณะที่มีแนวโน้มที่จะมีประสิทธิภาพส่วนใหญ่ในขณะที่เทคนิคการแนะนำศักยภาพสำหรับพฤติกรรมที่ไม่ได้กำหนด หากคุณไม่รู้สึกอยากเสี่ยงวิธีเมธอดอาจเป็นตัวเลือกที่ดีกว่า คำตอบที่นี่ให้โซลูชันเดียวกันผ่านทาง swizzling: stackoverflow.com/questions/19542942/…
Nathan Hosselton

64

หากคุณใช้ Swift คุณสามารถสร้างส่วนขยาย UILabel ได้:

extension UILabel {

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

}

และจากนั้นที่ที่คุณทำปรากฏตัวของคุณ proxying

UILabel.appearance().substituteFontName = applicationFont

มีเทียบเท่ารหัส Objective-C โดยใช้เป็นในทรัพย์สินที่มีชื่อUI_APPEARANCE_SELECTORsubstituteFontName

ส่วนที่เพิ่มเข้าไป

สำหรับกรณีที่คุณต้องการตั้งค่าแบบอักษรหนาและปกติแยก:

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

หมายเหตุ: หากคุณพบว่าการเปลี่ยนตัวหนาไม่ทำงานอาจเป็นไปได้ว่าชื่อแบบอักษรเริ่มต้นไม่มี "ปานกลาง" เปลี่ยนสายนั้นสำหรับการแข่งขันอื่นตามต้องการ (ขอบคุณ Mason ในความคิดเห็นด้านล่าง)


ข้อเสียอย่างหนึ่งที่ฉันพบคือเมื่อฉันเริ่มต้นการแจ้งเตือนด้วย UIAlertController ปุ่มที่มีรูปแบบ. Cancel จะเหมือนกับปุ่มที่มีรูปแบบเริ่มต้น (อย่างน้อยเมื่อใช้ GillSans) ในขณะที่ปกติ. ยกเลิกจะเป็นแบบอักษรน้ำหนักปกติและ. เริ่มต้นจะเป็นตัวหนา ความคิดใด ๆ
Mason G. Zhwiti

ขออภัยฉันหมายถึงป้ายกำกับยกเลิกโดยทั่วไปจะเป็นตัวหนาและโดยปกติแล้วค่าเริ่มต้นจะเป็นน้ำหนักปกติ
Mason G. Zhwiti

2
@ MasonG.Zhwiti ในกรณีนี้ฉันอาจตั้งค่าUILabelส่วนขยายเพื่อใช้ชื่อแบบอักษรเพิ่มเติมสำหรับตัวหนา จากนั้นในการsetทำตรวจสอบเพื่อดูว่า "ตัวหนา" อยู่ในชื่อตัวอักษรและไม่สนใจชุดในกรณีหนึ่งและใช้ในอื่น ๆ ฉันจะแก้ไขและเพิ่มตัวอย่าง
Sandy Chapman

@SandChapman ขอบคุณ! ฉันลองใช้เทคนิคใหม่นี้แล้วมันก็สมเหตุสมผล แต่ดูเหมือนจะไม่เหมาะกับฉัน ฉันใช้ GillSans และ GillSans-Bold บนเครื่องจำลอง iOS 8.3 คุณทดสอบเทคนิคนี้แล้วหรือยัง?
Mason G. Zhwiti

2
@SandChapman ฉันคิดออกว่าเกิดอะไรขึ้น แบบอักษรเริ่มต้นสำหรับ iOS 8 มีแนวโน้มที่จะเป็น HelveticaNeueInterface-Regular หรือ (สำหรับตัวหนา) HelveticaNeueInterface-MediumP4 ดังนั้นการมองหา "ตัวหนา" จึงไม่ตรงกับสิ่งใดเลย ฉันเปลี่ยนเป็นrangeOfString("Medium")และใช้งานได้
Mason G. Zhwiti

23

การพัฒนาจากคำตอบของ Hugues BR แต่การใช้วิธีการที่รวดเร็วฉันได้มาถึงโซลูชันที่ประสบความสำเร็จในการเปลี่ยนแบบอักษรทั้งหมดเป็นแบบอักษรที่ต้องการในแอปของฉัน

วิธีการที่มี 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
Fábio Oliveira

ขอบคุณสำหรับคำตอบฉันใช้โซลูชันอื่นในตอนนี้ ฉันจะตรวจสอบเมื่อฉันต้องการมันอีกครั้ง :)
Utku Yıldırım

2
ขอบคุณ @ FábioOliveiraมันใช้งานได้อย่างมีเสน่ห์! อีกเพียงสิ่งเดียวที่คุณต้องวาง #import <objc / runtime.h> บนส่วนหัวมิฉะนั้นคุณจะได้รับข้อผิดพลาดโดยใช้คลาส 'Method' (ข้อผิดพลาดที่ฉันได้รับใน XCode 6)
nahung89

ด้วยเหตุผลบางอย่างบน iOS 8 modals ( UIAlertController) จะไม่เปลี่ยนแบบอักษร
Randomblue

13

เพื่อให้คำตอบของ Sandy Chapman สำเร็จนี่คือวิธีแก้ปัญหาใน 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 ทุกตัวในตัวควบคุมซึ่งคุณต้องการเปลี่ยนแบบอักษรหรือไม่
Jules

ไม่คุณต้องใส่รหัสนี้หนึ่งครั้งทุกที่ในโครงการของคุณ ในappdelegateของคุณเช่น
Damien Debin

1
@DamienDebin ฉันต้องการใช้แบบอักษรตัวหนาเป็นตัวหนา แต่นี่เปลี่ยนเป็นตัวหนา ทางใดบ้าง?
Zeeshan

จริงแล้วใช้งานได้ แต่ควรเป็น "หมวดหมู่" หรือ "ส่วนขยาย" ความแตกต่างอธิบายไว้ที่นี่: stackoverflow.com/questions/7136124/…
Darius Miliauskas

4

ความคิดเห็นสำหรับ SWIFT 3.0 และคำเตือน SWIFT

คุณสามารถลบข้อความเตือนในบรรทัด:

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

โดยแทนที่ด้วย:

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

ฮ่า ๆ. ฉันไม่รู้ว่า Swift อนุญาตให้ใช้สิ่งนี้ Btw ฉันจะอัปเดตเป็นคำตอบด้านบน ขอบคุณ @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 คือการเปิดสตอรี่บอร์ดเป็นซอร์สโค้ด (สตอรี่บอร์ดควบคุมคลิกในเนวิเกเตอร์ไฟล์> "เปิดเป็น"> "ที่มา") จากนั้นทำการค้นหาและแทนที่


3

ประเภทแบบอักษรมักจะถูกตั้งค่าในรหัสและปลายปากกา / กระดานเรื่องราว

สำหรับรหัสเช่นHugues BR กล่าวว่าทำในประเภทสามารถแก้ปัญหาได้

สำหรับปลายปากกา / กระดานเรื่องราวเราสามารถเปลี่ยนวิธี Swizzling awakeFromNib เพื่อเปลี่ยนประเภทแบบอักษรเนื่องจากองค์ประกอบ UI จากปลายปากกา / กระดานเรื่องราวจะเรียกมันเสมอก่อนแสดงในหน้าจอ

ฉันคิดว่าคุณรู้จักAspects . มันเป็นไลบรารี่สำหรับการโปรแกรม AOP, โดยยึดตาม Method 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ของตัวเองหลังจากตรวจสอบการโพสต์ไม่กี่โพสต์มันครอบคลุมกรณีส่วนใหญ่เช่น:

ขั้นแรกให้เพิ่มแบบอักษรลงในโครงงานโครงการและไฟล์. 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 คุณสามารถให้ข้อมูลความขัดข้องเพิ่มเติมแก่เราได้หรือไม่
Javier Amor Penas

1
ความผิดพลาดขอโทษจากด้านของฉันตัวอักษรไม่ได้ระบุไว้ใน info.plist
shesh nath

@midhunp คุณช่วยให้ชัดเจนมากขึ้นเพื่อที่จะไม่ทำงานสำหรับคุณ? มันทำงานได้ดีสำหรับฉันด้วยแบบอักษรที่เป็นตัวหนา
Javier Amor Penas

2

อาจไม่ใช่คุณอาจจะตั้งค่าแบบอักษรบนการควบคุมของคุณเอง แต่คุณสามารถทำให้กระบวนการง่ายขึ้นโดยการรวมศูนย์ที่คุณได้รับแบบอักษรจากตัวอย่างเช่นให้ตัวแทนแอปหรือคลาสทั่วไปอื่นมีวิธีที่ส่งกลับค่า แบบอักษรและทุกสิ่งที่จำเป็นในการตั้งค่าแบบอักษรสามารถเรียกวิธีการนั้นได้ซึ่งจะช่วยในกรณีที่คุณต้องการเปลี่ยนแบบอักษรของคุณคุณต้องเปลี่ยนแบบอักษรในที่เดียวมากกว่าทุกที่ที่คุณตั้งค่าแบบอักษร ... อีกทางเลือกหนึ่งคือ องค์ประกอบ UI ของคุณที่จะตั้งค่าแบบอักษรโดยอัตโนมัติ แต่นั่นอาจเกินความเป็นจริง ..


สำหรับบันทึกนี่คือสิ่งที่ฉันทำ แต่ @Randall ต้องการตัวแทนและให้คำตอบที่ดี ฉันต้องการการสนับสนุนน้อยกว่า 5.0
Sam Jarman

4
ฉันไม่เห็นด้วยกับสิ่งที่คุณทำ คำตอบที่คุณเลือกไม่ถูกต้องเมื่อคำถามของคุณถูกแท็ก iphone-sdk-4.0
เปาโล Casaretto

@Sam Jarman คำตอบของ Randall ด้านล่างถูกต้อง - คุณสามารถทำเครื่องหมายไว้สำหรับผู้เยี่ยมชมในอนาคตได้ไหม?
บิล

1

นุ้ยเป็นทางเลือกให้กับพร็อกซี่ UIAppearance มันจะช่วยให้คุณสามารถควบคุมตัวอักษร (และคุณลักษณะอื่น ๆ อีกมากมาย) ของจำนวนมากของ UI ประเภทองค์ประกอบตลอดใบสมัครของคุณโดยเพียงแค่การปรับเปลี่ยนรูปแบบแผ่นซึ่งสามารถนำกลับมาใช้ในหลายโปรแกรม

หลังจากเพิ่มNUILabelคลาสในป้ายกำกับของคุณคุณสามารถควบคุมแบบอักษรในสไตล์ชีตได้อย่างง่ายดาย:

LabelFontName    String    Helvetica

หากคุณมีป้ายกำกับที่มีขนาดตัวอักษรแตกต่างกันคุณสามารถควบคุมขนาดได้โดยใช้คลาส Label, LargeLabel และ SmallLabel ของ NUI หรือสร้างชั้นเรียนของคุณเองได้อย่างรวดเร็ว


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 iOS 5.0+ UIApperanceพร็อกซีสามารถนำมาใช้ในการปรับแต่งลักษณะของอินสแตนซ์ทั้งหมดของชั้นเรียนอ่านรายละเอียดเพิ่มเติม

Xcodes auto complete ไม่แสดงคุณสมบัติที่มีทั้งหมดและอาจเกิดข้อผิดพลาด แต่คุณสามารถพิมพ์ออกมาและมันจะคอมไพล์

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

-1

เราได้ประสบความสำเร็จเหมือนกันในสวิฟท์ -Xcode 7.2 โดยใช้ผู้ปกครองควบคุมดูและควบคุมเด็กดู (มรดก)

File - ใหม่ - โกโก้ชั้นสัมผัส - 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 เพิ่ม TextLabel

    import UIKit

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

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

หรือทำเอง UILabel ชั้น (วิธี classing Sub) และเชื่อมโยงป้ายมันจำเป็น

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) 'for' การวนซ้ำ UIView สำหรับมุมมองย่อย ใช้งานได้กับ VC เฉพาะเท่านั้น

    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)    
                }               
            }       
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.