XCode - Change Default Global Font in Storyboard - ios

Very much like how we can set the Global Tint in Storyboard, Is it possible to set the global font-family as something else?
For example, I want to change the Global/Default Font from System to Source Sans Pro 16pt. However, what I have to do (to my knowledge) is one of the following:
Change font of each label, button, textField, etc. in Storyboard.
Set it via Swift ViewDidLoad Code (like this question) or through extensions as explained in this question
My Problem with (2) is that I do not get Visual Feedbacks like in (1) using storyboards. On the other hand, it is also not very eloquent as I have to manually set it anyway.
So, is there a way to change/set the default Storyboard font?

You can use the Appearance API, to ensure that all controls have the same font (at runtime)
Look at this question as to how to set the font for UIButton with Appearance.
For UILabel and UITextView, do the following. This can be done in AppDelegate application(_:didFinishLaunchingWithOptions:)
let labelAppearance = UILabel.appearance()
labelAppearance.font = UIFont.myFont()
let textFieldAppearance = UITextView.appearance()
textFieldAppearance.font = UIFont.myFont()
The previous solution, however will not update storyboard.
To see the changes visually on storyboard, you can look into the function
prepareForInterfaceBuilder()
Here is an answer that explains how to get it visually updated in storyboard, but for this you will need to use custom classes for your textFields, buttons, etc.
Code Example as per above link:
#IBDesignable
public class MyUILabel: UILabel {
public override func awakeFromNib() {
super.awakeFromNib()
configureLabel()
}
public override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
configureLabel()
}
func configureLabel() {
font = UIFont(name: Constants.DefaultFont, size: 40)
}
}

Related

Round button on custom class with UIAppearance

I am trying to apply styles on a custom class using UIAppearance()
class MainStyleButton: UIButton {}
with a code:
let buttonView = MainStyleButton.appearance()
buttonView.backgroundColor = Style.buttonColor
buttonView.layer.cornerRadius = 5
buttonView.layer.borderWidth = 5
buttonView.layer.borderColor = Style.buttonColor.cgColor
It works with color, but unfortunately doesn't make my button round. I would appreciate any tips.
Tested on simulator iPhone X, 8 with iOS 11.2.
I tried replicating your approach and set up a button. I tried to change the button's appearance in a UIViewController during viewDidLoad and also in the AppDelegate during applicationDidFinishLaunching using your code. I additionally tested changing the button type to .custom from the default type .system. None of this seemed to work, I could not override the same attributes that you couldn't.
From Apple's docs I understand that the button type defines its appearance and also which appearance attributes can be overridden:
A button’s type defines its basic appearance and behavior. You specify the type of a button at creation time using the init(type:) method or in your storyboard file. After creating a button, you cannot change its type.
I do not know why the attributes of interest to you are not changeable at this point
However I would like to offer a different approach that I personally use and allows you to change the buttons appearance. Since you already defined your custom class it is much simpler to define corner radius and other attributes that you would like, like so (or you could write a style function with parameters that you can call at any time, to be able to change the appearance based on where the button is used):
class MainStyleButton: UIButton {
override func awakeFromNib() {
layer.borderColor = Style.buttonColor.cgColor
layer.borderWidth = 5
layer.cornerRadius = 5
}
}
Or you can instantiate/use an IBOutlet for a system button and do this:
class MyViewController: UIViewController {
#IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// not necessary to do this is viewDidLoad, that's just my example
myButton.layer.borderColor = Style.buttonColor.cgColor
myButton.layer.cornerRadius = 5
myButton.layer.borderWidth = 5
}

Change font of UIPrintInteractionController

I have a UIPrintInteractionController that is created programatically. It is set to pull a pdf from my servers, and print said pdf. My question is how can I change the font of the view. I already have set the navbar font in my app delegate (so the font appears on all views), but this doesn't apply to the view. Any help is greatly appreciated. Thanks!
I figured it out. Create an extension of UILabel like so
extension UILabel {
var substituteFontName : String {
get { return self.font.fontName }
set { self.font = UIFont(name: newValue, size: self.font.pointSize) }
}
}
The in AppDelegate.swift, use this extension to change the font of every label in the entire application, INCLUDING the UIPrinterInteractionController.
UILabel.appearance().substituteFontName = "Font Name Here"
Killed two birds with one stone.

Storyboard Designtime Layout Attributes

This is a feature a like a lot when defining layouts for Android and that allows to define attributes just to design.
http://tools.android.com/tips/layout-designtime-attributes
But I didn't find any equivalent way to do the same when using storyboard to make iOS Apps.
At the moment I a cleaning all the design values on a viewDidLoad of my ViewController. Is there a way to define layout attributes as design placeholders and avoid making this setupClean step in all my view controllers?
When You want Instant Reflect of attributes/properties of particular componet in storyboard then you can achieve using #IBDesignable.
To achieve this You have to subcalss of that type of which you want to be reflected on storyboard.
Steps
Make a subclass of the type you want be reflected on storyboard, as in example here i am going to subclass UILabel as DGlabel
Make that calss as #IBDesignable, see the example
Assign that subclassed to the component from Identity Inspector, see screen shot
In subclassed calss (here in example DGLabel) declare variables of properties/attributes which you want be reflected on design as #IBInspectable, see example here i have decalred borderColor as #IBInspectable, this means this property will be listed on property inspector of Xcode
now you can change the value of that property from story board as screen shot below
import UIKit
#IBDesignable
class DGLabel: UILabel {
#IBInspectable var borderColor:UIColor = UIColor.red {
didSet {
reflectChange()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func reflectChange() {
self.layer.borderWidth = 1
self.layer.borderColor = borderColor.cgColor
}
}
Hope this will allow you to understand the process.
Yes you can do that by providing runtime attribute in "User defined runtime attributes" section under storyboard's Identity inspector. See below screenshot for setting UILabel's "text" keypath's runtime value as blank.
I think you can achieve something similar by using IBDesignable for your views. Then you may use prepareForInterfaceBuilder() and TARGET_INTERFACE_BUILDER to generate mock data for display in Interface Builder.
Did you mean this?
You can change Label Text value in storyboard from the "Attribute Inspector".

Swift2 override of highlighted/selected doesn't work

I'm creating a custom UIButton class and i'm trying to override the highlighted/selected methods but they aren't called. After a bit of searching i found that this code should be working:
override var highlighted: Bool {
didSet {
if highlighted {
self.backgroundColor = UIColor.whiteColor()
} else {
self.backgroundColor = UIColor.blackColor()
}
}
}
I did the same for selected. I also tried using willSet but no luck. I'm using swift2.0. Could that make the difference? Anyone knows why it isn't called?
You're going about this all wrong. No need to subclass. Just call setBackgroundImage:forState: with a black image for one state and a white image for the other.
Issue fixed. Due to the fact that i'm wokrking on an SDK shared library, I had to define the Module of my view controller and the Module of my button class. Once I did those, everything was working fluently.

UIAppearance, see result in Interface Builder?

I'm using UIAppearance a lot for my navigation controllers and other UI objects, and I was wondering if it's possible to have my related objects styled in Interface Builder (maybe with some magic voodoo of #IBDesignable?)
matt's comments on the question are correct. You're able to successfully use UIAppearance proxies in the prepareForInterfaceBuilder method.
Example:
#IBDesignable
class MyCustomView: UIView {
override func prepareForInterfaceBuilder() {
MyCustomView.appearance().backgroundColor = UIColor.redColor()
}
}
This will result in all MyCustomView instances to be rendered red in IB.

Resources