4

I've created a @IBDesignable subclass of UIView

The view has couple of labels and a text field.

When I try to change their value in the storyboard, the changes are not rendered. In constant changes in cornerRadius, borderWidth and borderColor are rendered on the storyboard.

What am I missing?

This is how it looks in storyboard:

enter image description here

This is how it looks in the simulator and how I expect it to look in the storyboard after rendering:

enter image description here

This is the code of the class:

import UIKit

@IBDesignable

class LoginTextField: UIView {


    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.cgColor
        }
    }

    @IBInspectable var title: String = "" {
        didSet {
            titleLabel.text = title
        }
    }

    @IBInspectable var placeholder: String = "" {
        didSet {
            textField.placeholder = placeholder
        }
    }

    @IBInspectable var message: String = "" {
        didSet {
            messageLabel.text = message
        }
    }

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var messageLabel: UILabel!

    @IBOutlet var contentView: UIView!

    override init(frame: CGRect) {

        super.init(frame: frame)
        commonInit()
    }

    override func awakeFromNib() {

        super.awakeFromNib()
    }

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {

        let bundle = Bundle.init(for: type(of: self))
        bundle.loadNibNamed("LoginTextField", owner: self, options: nil)
        addSubview(contentView)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
    }
}

Update: everything started to work all of a sudden enter image description here

Luda
  • 7,282
  • 12
  • 79
  • 139
  • What do you mean by: `In constant changes in cornerRadius, borderWidth and borderColor are rendered on the storyboard.`? Tried your code, works fine. As I change the value of cornerRadius in attributes inspector, the IB gets updated. – Glenn Posadas Jan 20 '19 at 09:24
  • I'm shocked that any are shown in the storyboard. The code is not compiled therefore `didSet` is not getting called. – impression7vx Jan 20 '19 at 09:26
  • @Glenn, correct she says that. But if you add a `Title` like she did does it keep it `Label` or go to your variable? – impression7vx Jan 20 '19 at 09:27
  • For your IBDesignable’s subviews, those should be added programmatically, not as separate IBOutlet’s. Also, it’s advisable to put you designable in a framework target, if you haven’t already. – Rob Jan 20 '19 at 09:41
  • 3
    Unrelated, but you shouldn’t call your `commonInit` from `prepareForInterfaceBuilder`. That method is for inserting dummy data, and the like, from IB, often not needed at all. Right now, you’re going to be calling it twice, once from `init` and once from `prepareForInterfaceBuilder`. – Rob Jan 20 '19 at 09:45
  • @Glenn, the IB gets updated when you change the value of cornerRadius, borderWidth and borderColor, but not of title, message and placeholder – Luda Jan 20 '19 at 11:03
  • @Rob, 1. If I add the views programatically I'll loose the advantage of xib which allows me to configure the views easily in IB. 2. What do you mean framework target? 3. Thank you for the comment regarding `prepareForInterfaceBuilder` and `commonInit`, I'll fix it. – Luda Jan 20 '19 at 11:06
  • @Kamran did you change the title in the IB and saw the title you set in the upper label in the IB? – Luda Jan 20 '19 at 13:57
  • "What do you mean framework target?” ... When Apple introduced designable views, they were explicit that the designables “must” go in a separate framework target. E.g. select “File” » “New” » “Target...” and then choose “Cocoa Touch Framework” and name it `FooKit` (as a matter of convention, just adding “Kit” to the end of the main target’s name). Then add your designables to that target and remove them from the main app target. Frankly, I doubt that this is the source of your issue, but historically was a source of issues. You will have to update “Module” in IB, below the base class. – Rob Jan 20 '19 at 16:32
  • @Kamran cam you please upload a screenshot of the rendered view controller in the IB – Luda Jan 20 '19 at 19:49
  • @Luda, I uploaded the complete sample [here](https://github.com/kamirana4/Temp). Hope you will get it. – Kamran Jan 21 '19 at 03:56
  • @Kamran That is so weird! Yesterday it didn't work. And today it is. Your project gave mine some energy boost – Luda Jan 21 '19 at 07:16
  • @Luda In my experience, `IBDesignable` are not very optimized for rendering by the interface builder so they cause unexpected errors once the storyboard is going to grow. Hence, at the moment i think it's wise to just run the code on simulator to see the result. – Kamran Jan 21 '19 at 07:20

0 Answers0