简体   繁体   中英

Strange issue with 2 initializers in Swift

I want to create 2 initializers for my custom button class which looks like:

protocol CustomButtonProtocol {
    var title: String { get set }
    var cornerRadius: CGFloat { get set }
    var backgroundColor: UIColor { get set }
}

struct Button: CustomButtonProtocol {
    var title: String
    var cornerRadius: CGFloat
    var backgroundColor: UIColor
}

class CustomButton: UIButton {
var title: String? {
    didSet {
        self.setTitle(title, for: .normal)
    }
}

var cornerRadius: CGFloat = 0.0 {
    didSet {
        self.layer.cornerRadius = cornerRadius
    }
}

var color: UIColor? {
    didSet {
        self.backgroundColor = color
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
}

init(with frame: CGRect, button: Button) {
    super.init(frame: frame)

    self.title = button.title
    self.cornerRadius = button.cornerRadius
    self.backgroundColor = button.backgroundColor
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

I want to have 2 initializers, the first one is simple init, the second one with my Button passed in, but the issue is that it changes ONLY background color but does not title and cornerRadius properties and I cannot find why it happens. Maybe I do not see something, could you please help me with finding the bug?

Consider that property observers willSet / didSet are not called in init methods

From the documentation :

When you assign a default value to a stored property, or set its initial value within an initializer, the value of that property is set directly, without calling any property observers.

A solution is to call the code in the observers also in the init method

init(with frame: CGRect, button: Button) {
    super.init(frame: frame)

    self.title = button.title
    self.setTitle(self.title, for: .normal)
    self.cornerRadius = button.cornerRadius
    self.layer.cornerRadius = self.cornerRadius
    self.color = button.backgroundColor
    self.backgroundColor = self.color
}

If color represents always the background color the property is actually redundant.

You have used didSet to update value to button property.

It won't call didSet while setting value inside init .

background color is getting set because you set backgroundColor by mistake in place of color

self.backgroundColor = button.backgroundColor

you should use/call below inside/outside init once.

self.setTitle(title, for: .normal)
self.layer.cornerRadius = cornerRadius
self.backgroundColor = color

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM