Ukuran Font Kustom di Kelas Ukuran Xcode 6 tidak berfungsi dengan baik dengan Font Kustom

104

Xcode 6 memiliki fitur baru di mana font dan ukuran font masuk UILabel, UITextFielddan UIButtondapat diatur secara otomatis berdasarkan kelas ukuran konfigurasi perangkat saat ini, langsung di storyboard. Misalnya, Anda dapat menyetel UILabeluntuk menggunakan ukuran font 12 pada konfigurasi "lebar apa pun, tinggi ringkas" (seperti pada iPhone dalam lanskap) dan ukuran 18 pada konfigurasi "lebar reguler, tinggi reguler" (seperti di iPad ). Informasi lebih lanjut tersedia di sini:

developer.apple.com/size_class

Ini adalah fitur hebat dalam teori karena dapat membuatnya tidak perlu menyetel font berbeda secara terprogram pada fitur UI berdasarkan konfigurasi perangkat. Saat ini, saya memiliki beberapa kode bersyarat yang menetapkan font berdasarkan jenis perangkat, tetapi jelas, itu berarti saya harus mengatur font secara terprogram di mana saja di seluruh aplikasi. Jadi awalnya saya sangat senang dengan fitur ini, tetapi saya menemukan bahwa fitur ini memiliki masalah parah dalam penggunaan sebenarnya untuk saya (mungkin bug). Perhatikan bahwa saya membangun berdasarkan SDK 8 dan menetapkan target penerapan minimum iOS 8 , jadi ini tidak ada hubungannya dengan kompatibilitas dengan versi lama iOS.

Masalahnya adalah ini: Jika saya menetapkan ukuran font yang berbeda untuk kelas ukuran yang berbeda dan menggunakan font "Sistem" yang disediakan oleh iOS , semuanya berfungsi seperti yang diharapkan, dan ukuran font berubah berdasarkan kelas ukuran. Jika saya menggunakan font khusus yang disediakan oleh aplikasi saya (ya, saya sudah menyiapkannya dengan benar di bundel aplikasi saya, karena berfungsi secara terprogram) dan menyetel font khusus ke label di storyboard XCode 6 , yang juga berfungsi seperti yang diharapkan. Tapi ketika saya mencoba menggunakan ukuran font khusus yang berbeda untuk kelas ukuran yang berbeda, di storyboard, tiba-tiba tidak berfungsi. Satu-satunya perbedaan dalam konfigurasi adalah font yang saya pilih (font kustom vs. font Sistem). Sebaliknya, semua font muncul di fileperangkat dan simulator sebagai font sistem default pada ukuran default , terlepas dari kelas ukurannya (dan saya memverifikasi melalui debugger bahwa itu menggantikan font sistem untuk font sebenarnya yang ditentukan di storyboard). Jadi pada dasarnya, fitur kelas ukuran tampaknya rusak untuk font khusus. Selain itu, yang menarik, font khusus benar-benar menampilkan dan menyesuaikan ukuran dengan benar di panel "Pratinjau" XCode 6 untuk pengontrol tampilan: ia berhenti bekerja hanya saat berjalan pada sistem iOS yang sebenarnya (yang membuat saya berpikir bahwa saya mengonfigurasinya dengan benar) .

Saya mencoba beberapa font kustom yang berbeda, dan sepertinya tidak berhasil untuk salah satu font tersebut, tetapi selalu berfungsi jika saya menggunakan "Sistem".

Bagaimanapun, apakah ada orang lain yang melihat masalah ini di Xcode 6 ?

Ada gagasan tentang apakah ini bug di iOS 8, Xcode, atau sesuatu

Apa yang saya lakukan salah?

Satu-satunya solusi yang saya temukan, seperti yang saya katakan, adalah terus mengatur font secara terprogram seperti yang saya lakukan untuk sekitar tiga versi iOS karena itu berfungsi.

Tetapi saya ingin dapat menggunakan fitur ini jika saya bisa membuatnya berfungsi dengan font khusus. Menggunakan font Sistem tidak dapat diterima untuk desain kami.


INFO TAMBAHAN: Pada Xcode 8.0, bug telah diperbaiki.

mnemia
sumber
3
Saya dapat mengonfirmasi bahwa ini masih terjadi dalam rilis app store xCode 6.1 (6A1052d).
jodm
3
Bukan solusi, tapi saya berhasil mengatasi masalah tersebut menggunakan Kategori. Kategori saya UILabel + Font.h (Saya punya satu untuk tombol juga) berisi kode berikut. - (void) awakeFromNib {float size = [self.font pointSize]; self.font = [UIFont fontWithName: @ "YourCustomFont" size: size]; } Jadi, ini memungkinkan kita untuk menggunakan kelas ukuran dengan font Sistem untuk menetapkan nilai titik dalam kelas ukuran yang berbeda, dan kategori tersebut memastikan bahwa font yang benar disetel. Mungkin Anda bisa mencobanya sampai Apple merilis pembaruan?
Daniel Retief Fourie
2
Masih belum terpecahkan di Xcode 6.3.1. Saya marah akan hal ini.
Kemarahan
7
Masih tidak berfungsi dengan Xcode 7 final. Tidak mengerti mengapa Apple tidak memperbaikinya.
ernesto
5
masih tidak berfungsi pada Xcode 7.2 iOS 9.2
Mojtaba

Jawaban:

41

Perbaikan cepat:

1) Tetapkan font sebagai Sistem untuk kelas ukuran

Pemeriksa atribut label

2) Subclass UILabel dan timpa metode "layoutSubviews" seperti:

- (void)layoutSubviews
{
  [super layoutSubviews];

   // Implement font logic depending on screen size
    if ([self.font.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location == NSNotFound) {
        NSLog(@"font is not bold");
        self.font = [UIFont fontWithName:@"Custom regular Font" size:self.font.pointSize];
    } else {
        NSLog(@"font is bold");
        self.font = [UIFont fontWithName:@"Custom bold Font" size:self.font.pointSize];
    }

}

Ngomong-ngomong, ini adalah teknik yang sangat nyaman untuk font ikonik

pisau cukur 28
sumber
Meskipun ini adalah solusi yang baik jika font yang digunakan di seluruh aplikasi sama, akan sedikit kurang nyaman jika Anda perlu menggunakan font yang berbeda di tempat yang berbeda, karena Anda harus memiliki subkelas yang berbeda, dll. Dalam kasus saya, saya sudah telah menyiapkan font terprogram, dan ada banyak cara berbeda untuk melakukannya. Tetapi inti pertanyaan saya bukanlah menanyakan bagaimana melakukan ini secara terprogram: ini untuk menanyakan mengapa ini tidak berfungsi dengan baik menggunakan Storyboards (ini adalah bug Apple).
mnemia
@nemia Saya setuju. Tujuan saya hanya untuk menunjukkan satu cara bagaimana menangani bug itu.
pisau cukur28
1
Bekerja dengan baik. Anda tidak perlu membuat subclass UILabel, Anda dapat mengganti metode ini dalam tampilan yang menyimpan label dan melakukan self.label.font = ...cara ini Anda dapat menggunakan font yang berbeda di tempat yang berbeda.
KPM
Atau Anda dapat mengatur @IBInspectable, untuk menyimpan nama font, untuk menggunakan kembali kelas label kustom yang sama dan meminta font yang berbeda langsung di storyboard.
Craig Grummitt
Apakah ada solusi serupa untuk UITextField?
Chris Byatt
17

Setelah mencoba semuanya, saya akhirnya menetapkan kombinasi solusi di atas. Menggunakan Xcode 7.2, Swift 2.

import UIKit

class LabelDeviceClass : UILabel {

    @IBInspectable var iPhoneSize:CGFloat = 0 {
        didSet {
            if isPhone() {
                overrideFontSize(iPhoneSize)
            }
        }
    }

    @IBInspectable var iPadSize:CGFloat = 0 {
        didSet {
            if isPad() {
                overrideFontSize(iPadSize)
            }
        }
    }

    func isPhone() -> Bool {
        // return UIDevice.currentDevice().userInterfaceIdiom == .Phone
        return !isPad()
    }

    func isPad() -> Bool {
        // return UIDevice.currentDevice().userInterfaceIdiom == .Pad
        switch (UIScreen.mainScreen().traitCollection.horizontalSizeClass, UIScreen.mainScreen().traitCollection.verticalSizeClass) {
        case (.Regular, .Regular):
            return true
        default:
            return false
        }
    }

    func overrideFontSize(fontSize:CGFloat){
        let currentFontName = self.font.fontName
        if let calculatedFont = UIFont(name: currentFontName, size: fontSize) {
            self.font = calculatedFont
        }
    }

}
  • @IBInspectable memungkinkan Anda mengatur ukuran font di Storyboard
  • Ini menggunakan didSetpengamat, untuk menghindari perangkap dari layoutSubviews()(loop tak terbatas untuk ketinggian baris tampilan tabel dinamis) dan awakeFromNib()(lihat komentar @ cocoaNoob)
  • Ini menggunakan kelas ukuran daripada idiom perangkat, dengan harapan pada akhirnya menggunakan ini dengan @IBDesignable
  • Sayangnya, @IBDesignabletidak berfungsi traitCollectionmenurut artikel tumpukan lainnya ini
  • Pernyataan saklar koleksi sifat dijalankan pada UIScreen.mainScreen()bukan selfper artikel tumpukan ini
Robert Chen
sumber
Jawaban terbaik, Tapi sayangnya di bawah Voted..Thanks
Rohit Pradhan
9

Solusi untuk UILabel: pertahankan ukuran font yang sama di semua Kelas Ukuran, tetapi ubah tinggi label Anda sesuai di setiap Kelas Ukuran. Label Anda harus mengaktifkan tautan otomatis. Ini bekerja dengan baik dalam kasus saya.

Phil
sumber
1
Saya dapat melakukan hal yang sama dengan mengubah lebar label saya di setiap Kelas Ukuran. Tip bagus!
dmzza
1
Saya tidak mendapatkan font menyusut dengan menyetel tinggi tetap yang lebih kecil untuk UILabel saya, bagaimana tepatnya Anda membuatnya berfungsi? adjustsFontSizeToFitWidthtampaknya hanya berfungsi untuk lebar (yang tidak dapat saya gunakan karena teks labelnya dinamis).
ernesto
Saya memiliki masalah yang sama dengan menyesuaikan agar sesuai lebar
Jules
1
Saya akhirnya menetapkan batasan ketinggian Label secara proporsional dengan ketinggian tampilan super. Itu berfungsi dengan baik selama Anda menyetel parameter "Garis" dari Label di IB ke 0.
Dorian Roy
8

Bug ini (dan bug terkait Xcode - Size Classes lainnya) membuat saya sangat sedih baru-baru ini karena saya harus melalui file storyboard besar yang meretas semuanya.

Untuk siapa pun yang berada dalam posisi ini, saya ingin menambahkan sesuatu di atas jawaban @ razor28 untuk mengurangi rasa sakit.

Di file header subclass kustom Anda, gunakan IBInspectableuntuk atribut runtime Anda. Ini akan membuat atribut ini dapat diakses dari "Attributes Inspector", secara visual tepat di atas posisi default untuk pengaturan font.

Contoh penggunaan:

@interface MyCustomLabel : UILabel

    @property (nonatomic) IBInspectable NSString *fontType;
    @property (nonatomic) IBInspectable CGFloat iphoneFontSize;
    @property (nonatomic) IBInspectable CGFloat ipadFontSize;

@end

Ini akan sangat membantu menghasilkan keluaran ini:

masukkan deskripsi gambar di sini

Manfaat tambahannya adalah sekarang kita tidak perlu menambahkan atribut runtime secara manual untuk setiap label. Ini adalah yang paling dekat yang bisa saya dapatkan dengan perilaku yang dimaksudkan XCode. Semoga perbaikan yang tepat sedang dalam perjalanan dengan iOS 9 musim panas ini.

joakim
sumber
Saya menambahkan sesuai instruksi Anda tetapi saya tidak dapat menemukan akses "Atribut Inspektur" secara visual di xib jadi bagaimana mencapainya?
Darshan Kunjadiya
3

Solusi serupa dengan @ razor28 tapi saya pikir sedikit lebih universal. Juga, berfungsi dengan baik pada versi iOS yang lebih lama

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

Vitaly
sumber
Dan tentu, Anda bisa menyetel properti overrideFontName di Interface Builder yang memungkinkan untuk menghindari penulisan kode yang tidak perlu
Vitaly
Ini tidak berhasil untuk saya, saya mencantumkan semua font yang diinstal dalam metode di atas dan font saya terdaftar dan ditetapkan dalam variabel tetapi tidak mengubah tampilan font di label pada simulator dan saya menganggap perangkat
Jules
3

Bug tersebut masih berlaku di XCode 7.0 GM.

Solusi Razor28 menyebabkan loop tak terbatas dalam beberapa kasus. Pengalaman saya telah menggunakannya dalam hubungannya dengan SwipeView .

Sebaliknya, saya menyarankan Anda:

1) Subclass UILabel dan timpa setFont:

- (void)setFont:(UIFont *)font
{
    font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize];
    [super setFont:font];
}

2) Setel kelas kustom UILabels Anda dan kemudian setel kelas ukuran font dengan menggunakan font Sistem

masukkan deskripsi gambar di sini

Foti Dim
sumber
@ Maarten1909 Apakah Anda mengacu pada solusi atau cara Xcode langsung? Jika yang pertama dapat Anda sebutkan versinya jadi saya mencoba mereproduksinya?
Foti Redup
Sepertinya saya telah menggunakan nama keluarga font yang salah sepanjang waktu. Ternyata dalam kasus seperti itu font di-reset ke font sistem dengan ukuran 14.0 pint. Salahku. Tapi mungkin berguna untuk orang lain!
Berendschot
0

Masalahnya masih ada bahwa Anda tidak dapat menggunakan fitur untuk mengatur Font untuk kelas ukuran yang berbeda dari pembuat antarmuka.

Cukup atur font berdasarkan perangkat yang Anda inginkan seperti di bawah ini:

if (Your Device is iPAd) //For iPad
{
   [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; 
}
else  //For Other Devices then iPad
{
   [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; 
}

Ini berfungsi dengan sempurna di semua perangkat.

Nirmit Dagly
sumber
0

Tak satu pun dari ini berhasil untuk saya, tetapi ini berhasil. Anda juga perlu menggunakan font sistem di IB

#import <UIKit/UIKit.h>

@interface UILabelEx : UILabel


@end

#import "UILabelEx.h"
#import "Constants.h"

@implementation UILabelEx

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
    [super traitCollectionDidChange: previousTraitCollection];

    self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize];   
}
@end
Jules
sumber
0

Masih belum ada jawaban yang benar. Kode ini berfungsi dengan baik untuk saya. Anda harus menonaktifkan ukuran font untuk kelas ukuran di pembuat antarmuka terlebih dahulu. Di IB Anda dapat menggunakan font khusus.

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
    [super traitCollectionDidChange: previousTraitCollection];

    if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass)
        || self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass) {

         self.textField.font = [UIFont fontWithName:textField.font.fontName size:17.f];

    }
}
Max Smirnov
sumber
0

Kombinasi dari beberapa jawaban di atas sangat membantu. Inilah cara saya memecahkan bug IB melalui ekstensi UILabel Swift:

import UIKit

// This extension is only required as a work-around to an interface builder bug in XCode 7.3.1
// When custom fonts are set per size class, they are reset to a small system font
// In order for this extension to work, you must set the fonts in IB to System
// We are switching any instances of ".SFUIDisplay-Bold" to "MuseoSans-700" and ".SFUIDisplay-Regular" to "MuseoSans-300" and keeping the same point size as specified in IB

extension UILabel {
    override public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass) {
            //let oldFontName = "\(font.fontName)-\(font.pointSize)"

            if (font.fontName == systemFontRegular) {
                font = UIFont(name: customFontRegular, size: (font?.pointSize)!)
                //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
            }
            else if (font.fontName == systemFontBold) {
                font = UIFont(name: customFontBold, size: (font?.pointSize)!)
                //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
            }
        }
    }
}
benjam
sumber
-1

Saya menggunakan Swift, XCode 6.4. Jadi inilah yang saya lakukan

import Foundation
import UIKit

    @IBDesignable class ExUILabel: UILabel {

        @IBInspectable var fontName: String = "Default-Font" {
            didSet {
                self.font = UIFont(name: fontName, size:self.font.pointSize)
            }
        }

        override func layoutSubviews() {
            super.layoutSubviews()
            self.font = UIFont(name: fontName, size:self.font.pointSize)
        }
    }
  1. Goto Designer -> Identity Inspector -> Setel kelas ke ExUILabel

  2. Lalu pergi ke Attribute inspector in designer dan atur nama font.

kakopappa.dll
sumber
-1

Saya telah menemukan perbaikan yang lebih cepat (saya berasumsi Anda selalu menggunakan satu font khusus Anda).

Buat kategori untuk UILabel dan sertakan dalam file menggunakan storyboard buggy dengan kelas ukuran dan pengaturan font khusus untuk berbagai kelas:

@implementation UILabel (FontFixForSizeClassesAppleBug)

- (void)layoutSubviews
{
    [super layoutSubviews];
    if([[UIFont systemFontOfSize:10].familyName isEqualToString:self.font.familyName]) {
        //workaround for interface builder size classes bug which ignores custom font if various classes defined for label: http://stackoverflow.com/questions/26166737/custom-font-sizing-in-xcode6-size-classes-not-working-properly-w-custom-fonts
        self.font = [UIFont fontWithName:@"YOUR_CUSTOM_FONT_NAME" size:self.font.pointSize];
    }
}

@end

Cukup gunakan font khusus Anda di storyboard. Ketika juru bahasa buggy akan menggunakan font sistem, bukan milik Anda, kategori ini akan mengubahnya ke font khusus Anda.

Heps
sumber
-1: Bukan ide yang baik untuk mengganti metode dalam kategori seperti ini. Alasan: stackoverflow.com/questions/5272451/… Sebaliknya, harus swizzle (meskipun hacky) atau subclass.
JRG-Developer
-6

Saya memiliki masalah yang sama dan menemukan satu yang tidak terlalu jelas, tetapi solusi yang bagus!

  1. Pertama, Anda mengatur ukuran font yang diperlukan di storyboard dengan nama font sistem.
  2. Kemudian ke label ini Anda menetapkan tag dari 100 hingga 110 (atau lebih, tetapi 10 selalu cukup bagi saya dalam satu pengontrol tampilan).
  3. Kemudian letakkan kode ini ke file sumber VC Anda dan jangan lupa untuk mengubah nama font. Kode dengan cepat.
override func viewDidLayoutSubviews() {
    for i in 100...110 {
        if let label = view.viewWithTag(i) as? UILabel {
            label.font = UIFont(name: "RotondaC-Bold", size: label.font.pointSize)
        }
    }
}
serg_ov
sumber
1
Jangan gunakan tag. Gunakan IBOutlets. Tag buruk. Lihat WWDC 2015 sesi 231: “Jika Anda menggunakan View With Tag atau Set Tag UIView API dan kode pengiriman, saya akan mendorong Anda untuk menjauh dari itu. Sebagai gantinya, deklarasikan properti di kelas Anda, dan kemudian Anda akan memiliki koneksi nyata ke tampilan yang Anda perlukan nanti. ”
KPM
Saya sedih karena solusi ini tidak sempurna, tetapi berhasil!
serg_ov
-8
  • tambahkan Font yang disediakan oleh aplikasi ke dalam aplikasi Anda .plist
  • tambahkan file .ttf Anda ke item 0
  • gunakan [UIFont fontWithName: "example.ttf" size: 10]
pengguna2612184
sumber
Ini bukanlah jawaban untuk masalah ini. Jelas Anda dapat menggunakan font khusus secara terprogram, tetapi pertanyaan saya merujuk pada bug di iOS 8 yang mencegah font kustom berubah secara otomatis tergantung pada kelas ukuran.
mnemia