I'm in the process of converting a custom UIButton
from Objective-C to Swift which has custom properties and default values for those properties:
MyButton.h
@interface MyButton : UIButton
@property (nonatomic, strong) IBInspectable UIColor *buttonColor;
@property (nonatomic, strong) IBInspectable UIColor *buttonSelectedColor;
// ...
@end
MyButton.m
@implementation MyButton
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self adjustButtonColor];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self adjustButtonColor];
}
return self;
}
- (void)setSelected:(BOOL)selected
{
[super setSelected:selected];
[self adjustButtonColor];
}
- (void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
[self adjustButtonColor];
}
- (void)adjustButtonColor
{
if (self.selected || self.highlighted) {
self.backgroundColor = [self buttonSelectedColor];
} else {
self.backgroundColor = [self buttonColor];
}
}
#pragma mark - Default colors
- (UIColor *)buttonColor
{
if (!_buttonColor) {
_buttonColor = [UIColor grayColor];
}
return _buttonColor;
}
- (UIColor *)buttonSelectedColor
{
if (!_buttonSelectedColor) {
_buttonSelectedColor = [self.buttonColor colorWithAlphaComponent:.5];
}
return _buttonSelectedColor;
}
#pragma mark - Public
- (void)setButtonColor:(UIColor *)buttonColor
{
_buttonColor = buttonColor;
[self updateButton];
}
@end
I have attempted to replicate this pattern in Swift with public vars which return a default value, or access a private optional variable which is returned if it exists. I have also overridden the selected
and highlighted
properties, updating the button colors in didSet
:
class MyButton: UIButton {
private var _buttonColor: UIColor?
var buttonColor: UIColor {
get {
if let color = _buttonColor { return color }
return UIColor.grayColor()
} set {
_buttonColor = newValue
}
}
private var _buttonSelectedColor: UIColor?
var buttonSelectedColor: UIColor {
get {
if let selectedColor = _buttonSelectedColor { return selectedColor }
return self.buttonColor.colorWithAlphaComponent(0.5)
} set {
_buttonSelectedColor = newValue
}
}
override var selected: Bool {
didSet {
adjustButtonColor()
}
}
override var highlighted: Bool {
didSet {
adjustButtonColor()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
adjustButtonColor()
}
override init(frame: CGRect) {
super.init(frame: frame)
adjustButtonColor()
}
func adjustButtonColor() {
if selected || highlighted {
backgroundColor = buttonSelectedColor
} else {
backgroundColor = buttonColor
}
}
}
A few questions:
Is this an appropriate use of private variables? Is there any way to accomplish the behavior I want with a single variable rather a second optional settable variable for each color?
Is overriding
UIButton
properties to calladjustButtonColor
indidSet
abuse of the getter/setter?If
initWithCoder
is a failable initializer do I need to check ifself
isnil
before callingadjustButtonColor()
?