Search code examples
uiviewinterface-builderxcode8ibdesignable

@IBDesignable not showing background color in IB


I have a UIView as below:

import UIKit

@IBDesignable
class CHRAlertView: UIView {

    @IBOutlet var icon:UILabel!
    @IBOutlet var alertText:UITextView!

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

        self.initialize()
    }

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

        self.initialize()
    }

    private func initialize(){
        self.backgroundColor = UIColor.green
    }

}

Based on how @IBDesignable works, this should show up in IB with a green background, but I get the clear color like this:

enter image description here

Why is this not functioning as expected? I need the background color to show in IB based on the defaults set in my @IBDesignable.


Solution

  • Since backgroundColor is an IB property not created via @IBInspectable, it always seems to overwrite whatever is in the init or draw methods. Meaning, if it is "default" in IB, it causes it to be overwritten with nil. However, if set in the prepareForInterfaceBuilder method backgroundColor works and shows in IB. So, the backgroundColor, it can be reasonably assumed, must be set at runtime. To do this I have the below:

    //------------------
        //Setup and initialization
        //------------------
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            self.initialize()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            self.initialize()
        }
    
        //Setups content, styles, and defaults for the view
        private func initialize(){
            self.staticContent()
            self.initStyle()
        }
    
        //Sets static content for the view
        private func staticContent() {
    
        }
    
        //Styles the view's colors, borders, etc at initialization
        private func initStyle(){
    
        }
    
        //Styles the view for variables that must be set at runtime
        private func runtimeStyle(){
            if self.backgroundColor == nil {
                self.backgroundColor = UIColor.green
            }
        }
    
        override func prepareForInterfaceBuilder() {
            self.runtimeStyle()
        }
    
        override func awakeFromNib() {
            super.awakeFromNib()
    
            self.runtimeStyle()
        }
    

    This defaults the backgroundColor if it is "default" (read nil) in IB to a color, but does not use the UIColor.green if a backgroundColor is set in IB, which is exactly what I need.

    Shoutout to Eridius in the #swift-lang irc for helping me get to this answer.