3

I have a UIView that is is @IBDesignable

@IBDesignable
class MyView: UIView {

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        sharedInit()
    }

    private func sharedInit(){
        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = .blue
    }

}

When I place this a UIView in the Storyboard, and assigned its class to MyView in the Identity inspector, the UIView still has a default background colour. Why is its background colour not UIColor.blue in the Storyboard? And, how can I make it like this, please?

Thanks for any help.

ajrlewis
  • 2,968
  • 3
  • 33
  • 67
  • 1
    `init` is used in *runtime* - and Interface Builder is *design-time*. While this may not work, look into using `prepareForInterfaceBuilder()` for seeing `sharedInit`. –  Jul 24 '18 at 11:35

3 Answers3

10

Initializer which initialize this view from storyboard will call on runtime, for updating view within storyboard in compile time you should try to include prepareForInterfaceBuilder which updates storyboard xib files in compile time.

I suggest you to do multiple things when you are going to create @IBDesignable classes :

  1. Mark class with @IBDesignable tag
  2. Mark UIView property with @IBInspectable, then you will be able to change the value for this property using StoryBoard
  3. Set the configuration code in willSet of that property which is observer for changes before the property takes the value, or didSet after the property received the value.
  4. Do your additional setup in prepareForInterfaceBuilder() which is overriding from its super class kind of UIView

Simple and easy !

Your code should looks like this :

Swift 5 :

import UIKit

@IBDesignable
class myView: UIView {

  @IBInspectable var storyBoardColor : UIColor = .red {         
    willSet(myVariableNameToCatch) {
      self.backgroundColor = myVariableNameToCatch
    }
   }

  fileprivate func sharedInit(){
    translatesAutoresizingMaskIntoConstraints = false
    backgroundColor = storyBoardColor
  }

  override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()
    sharedInit()
  }
}

myView had initial value of red for storyBoardColor and you can change it from storyBoard ;)

enter image description here

Mohammad Reza Koohkan
  • 1,656
  • 1
  • 16
  • 36
  • @thibautnoah hi, i reminded him in section (3), and told him how to implement structre base. the answer could found in section (3), and for the functionality i wanted for everyone to know how does it works.. but thanks maybe i should explain less. – Mohammad Reza Koohkan Jul 26 '19 at 15:38
  • 1
    @mohamadrezakoohkan the view is not init in the first place.. hence why i said you didn't answer the question. I agree on the inspectable part but you changed the structure of the class itself. – thibaut noah Jul 27 '19 at 16:11
2

Once you make your view with tag @IBDesignable. next thing is to set your properties with @IBInspectable.

@IBDesignable
class MyView: UIView {

    @IBInspectable var myBackgroundColour: UIColor? = nil {
        willSet(v) {
            self.backgroundColor = v
        }
    }
   // YOUR EXISTING CODE HERE
}

Now, when you set the MyView as a class name in Identity Inspector. You will be able to see your inspectable property in Attributes Inspector. there you can set the colour and it will be reflected instantly to your custom view.

I don't see any usefulness to set the background colour with your custom property because, UIView has the default property to set the background colour.

Hope it helps.

Bhavin Kansagara
  • 2,866
  • 1
  • 16
  • 20
1

Swift 4.2 tested and working. This is the cleanest solution.

In Xcode make sure Editor -> Automatically refresh views is checked.

import UIKit

@IBDesignable
class BoxView: UIView {

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer.borderColor = borderColor?.cgColor
        layer.borderWidth = borderWidth
        layer.cornerRadius = cornerRadius
    }

    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.cgColor
            setNeedsLayout()
        }
    }

    @IBInspectable var borderWidth: CGFloat = 0.0 {
        didSet {
            layer.borderWidth = borderWidth
            setNeedsLayout()
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            layer.cornerRadius = cornerRadius
            setNeedsLayout()
        }
    }
}
  1. Create the BoxView.swift file above.
  2. Select a UIView in InterfaceBuilder.
  3. In the Identity Inspector select Custom Class -> Class to "BoxView".
  4. In the Attributes Inspector set borderColor, borderWidth, and borderRadius.
Noah Prado
  • 11
  • 2