Xcode 6 has a new feature where fonts and font sizes in UILabel
, UITextField
, and UIButton
can be s
None of these worked for me, but this did. You also need to use the system font in 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
The bug is still valid in XCode 7.0 GM.
Razor28's solution causes infinite loops in some cases. My experience has been with using it in conjunction with SwipeView.
Instead, I suggest that you:
1) Subclass UILabel and override setFont:
- (void)setFont:(UIFont *)font
{
font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize];
[super setFont:font];
}
2) Set the custom class of your UILabels and then set the font size classes by using System font
After trying everything, I eventually settled on a combination of the above solutions. Using 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
lets you set the font size in the StoryboarddidSet
observer, to avoid the pitfalls from layoutSubviews()
(infinite loop for dynamic table view row heights) and awakeFromNib()
(see @cocoaNoob's comment)@IBDesignable
@IBDesignable
doesn't work with traitCollection
according to this other stack articleUIScreen.mainScreen()
rather than self
per this stack articleA combination of some of the later answers above were helpful. Here's how I solved the IB bug via a Swift UILabel extension:
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)")
}
}
}
}
I am using Swift, XCode 6.4. So this is what I did
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)
}
}
Goto Designer -> Identity Inspector -> Set the class to ExUILabel
Then go to Attribute inspector in designer and set the font name.