Subclassed UIButton title font size changing unexpectedly - swift

I'm using protocol delegate to set the title of a UIButton. However, somewhere along the line the font size is unexpectedly changing from 14 to 17. I've tried subclassing the button to keep the font at size 14, but clearly something is going wrong. It's been suggested that perhaps there's a conflict somewhere with the font size. However, I can't find any code that creates conflict.
Subclassed button:
import UIKit
class typeButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel?.font = UIFont(name: "Helvetica", size: 14)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Protocol extension:
extension ObservationDetailViewController: MushroomTypeDelegate {
func didSelectMushroom(name: String) {
typeButton.setTitle(name, for: .normal)
observation?.type = name
}
} // End of Extension
The button is classed via Storyboard. If I place a breakpoint on the line setting the button title typeButton.setTitle(name, for: .normal) it shows the font at size 14 . Yet, as I move past the breakpoint the font is unexpectedly changed to a larger size. I was able to use attributed text, & setAttributedTitle to fix this, but I'm curious why the font size is being changed.
Link to GitHub file

Try setting the font size in init?(coder aDecoder: NSCoder) since you classed the button from storyboard:
class TypeButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
titleLabel?.font = UIFont(name: "Helvetica", size: 14)
}
}
And make sure the font name is correct.

Related

What to use as NSCoder to initialize a View?

Hey guys I created a new custom View Class and now I want to build a instance of it, I initialized it with the following code:
required init?(coder aCoder: NSCoder) {
super.init(coder: aCoder)
tapRecognizer = UITapGestureRecognizer(
target: self, action: #selector(handleBarTap))
addGestureRecognizer(tapRecognizer)
}
deinit {
removeGestureRecognizer(tapRecognizer)
}
And this is the instance, but what can I use as coder?
lazy var chartView = TutorialChartView(coder: )
Thanks in advance!
When you say View, do you mean UIView? The problem is that that's the wrong initializer. init(coder:) is not something you call; it's a process initiated by the storyboard when there is one of these things in the storyboard and you load that view controller.
The code UIView designated initializer is init(frame:). Implement that and call it, and you're all set.
(You may also have to provide an implementation of init(coder:) but it should just throw a fatalError, because you do not expect to be called this way.)
You should cannot use coder as initializer for creating class, use frame instead, here is your code written in frame-style initializing.
override init(frame: CGRect) {
super.init(frame: frame)
tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleBarTap))
addGestureRecognizer(tapRecognizer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Here is how you use it:
lazy var chartView = TutorialChartView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)

Crash when using loadNibNamed

This is my code:
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
let mainBundle = Bundle.main
mainBundle.loadNibNamed("iconView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
I copied it from step 8 in this tutorial that I've seen (I only changed the name in the code to my xib file: "iconView").
But for some reason it fails:
I already tried all of the solutions in stackoverflow, but nothing helped me.
Here is my xib file:
I really don't know what to do.
I'm using Xcode 12 beta 6, iOS 14 beta 6
UPDATE
Okay, a lot of people saied in the comments of the tutorial that
This causes an infinite-loop calling commonInit().
So now I know what the issue is, but I still don't know how to solve it. Any ideas?
You probably have to remove Class from your View.
First select your View (in your case iconView):
and then clear whatever there is in the class field:

custom class swift setting constraints to superview

I want to create a custom UIView that I can add to any view and have it show a red error message like instagram does in the picture. I am able to do this programmatically in my view controller but want to create a modular class that I can add it into any view where I want to show an error. My question is how can I add constraints to superview in a custom class?
For example how would I do:
topAnchor.constraint(equalTo: view.topAnchor, constant: 0)
leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0)
rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0)
widthAnchor.constraint(equalTo: errorLabel.frame.size.height,0)
In a custom class so that I don't have to do it in my view controller? Can I access whatever superView's constraints so that my view is always located at the top?
class CustomUIAlertView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Can you give guidance on how to approach this? I feel like I am missing something basic.
I think the best way is to pass the superview as parameter to the init method.
Something like that:
class CustomUIAlertView : UIView {
weak var parent:UIView
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
required init(frame:CGRect, superview:UIView) {
super.init(frame: frame)
self.parent = superview
}
}

UILabel subclass appearance in Storyboard

I have created a subclass of UILabel called MyUILabel. The only thing changed is the font and font-size. It appears as expected when I run the app. However, the in the Storyboard, the default UILabel is showed. Is there any way to make Storyboards show the font and font-size from my subclass?
MyUILabel:
public class MyUILabel : UILabel {
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.font = UIFont(name: Constants.DefaultFont, size: 30)
}
}
You could make it #IBDesignable, and then implement prepareForInterfaceBuilder:
#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)
}
}
Note, IB didn't like it when I implemented init(coder:), so I moved it into awakeFromNib.
Also note that when you make an #IBDesignable class, Apple advises that you create a separate target (e.g. "File" - "New" - "Target..." - "Cocoa Touch Framework") for this designable class. For more information, see WWDC 2014 video What’s New in Interface Builder.

swift IBDesignable view not show in storyboard

I want to custom a 5-star UIView,also I want it to be render in storyboard. So I decide to use #IBDesignable and #IBInspectable.The following is my code.
import UIKit
#IBDesignable
class RatingView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpView()
}
func setUpView() {
let imageView = UIImageView(frame:CGRectMake(0, 0, 50,50))
imageView.image = UIImage(named: "star")
addSubview(imageView)
}
}
And then in my storyboard , I pull a UIView into my canvas,and set Custom class to my custom view as RatingView.The compiler starts to compile storyboard file and I just wait for the custom view to be renderd in canvas.Here is the screenshot.
The state is "up to date",but the view has not been renderd.The view is just staying white,what I want to see is the image I add to the parent view.
When I use UILabel instead of UIImageView, the label is renderd in the canvas but not the UIImageView,how can I render my lovely star image in my canvas.(Images.xcassets has star.png file)
use UILabel instead of UIImageView
func setUpView() {
let label = UILabel(frame: CGRectMake(0, 0, 50, 50))
label.text = "text"
addSubview(label)
}
result:
I was trying to do the same exact thing. You need to put the view in a framework. As #Benson Tommy said in the comments take a look at WWDC 2014 session 411.
Here is a link to the session:https://developer.apple.com/videos/wwdc/2014/#411
Here is a link to the transcript of the session: http://asciiwwdc.com/2014/sessions/411