IBInspectable not updating in storyboard but works on simulator
Asked Answered
B

6

7

I can view the changes made using IBInspectable on my simulator but not in my storyboard

I tried reinstalling my Xcode but it didn't fix this issue. Here are some screenshots :

Storyboard

Simulator

So i know my code works fine because it runs in the simulator and this is a new project altogether so I do not have any of the "Storyboard might still be loading the changes" problems.

import UIKit

extension UIView {

@IBInspectable
var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set {
        layer.cornerRadius = newValue
        layer.masksToBounds = newValue > 0
    }
}

@IBInspectable
var borderWidth: CGFloat {
    get {
        return layer.borderWidth
    }
    set {
        layer.borderWidth = newValue
    }
}

@IBInspectable
var borderColor: UIColor? {
    get {
        let color = UIColor(cgColor: layer.borderColor!)
        return color
    }
    set {
        layer.borderColor = newValue?.cgColor
    }
}

@IBInspectable
var shadowRadius: CGFloat {
    get {
        return layer.shadowRadius
    }
    set {
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.shadowOpacity = 0.4
        layer.shadowRadius = shadowRadius
    }
}
}
Backstroke answered 28/2, 2018 at 6:4 Comment(2)
Is your code missing @IBDesignable?Dappled
Oops made a boo boo on the title there sorryBackstroke
M
15

Firstly, you need @IBDesignable directive to render the updates in Storyboard whereas @IBInspectable is only to access the property directly in the Storyboard.

Secondly, you have extended the UIView class to show the inspectable properties in the Storyboard but without @IBDesignable.

Now you would think adding @IBDesignable would solve your problem but sadly you can't apply @IBDesignable on an extension like so:

@IBDesignable //won't work on an extension
extension UIView {
    //...
}

You can only apply the @IBDesignable directive on a class you have access to, like so:

@IBDesignable
class MyPrettyDesignableView: UIView {
    //...
}

Solution:

Bottomline is that you should subclass UIView and apply the @IBDesignable directive on this class.
Basically, your only option is:

@IBDesignable
class MyPrettyDesignableView: UIView {
    
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            self.layer.cornerRadius = cornerRadius
            self.layer.masksToBounds = true
        }
    }
    
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            self.layer.borderWidth = borderWidth
        }
    }
    
    @IBInspectable var borderColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1) {
        didSet {
            self.layer.borderColor = borderColor.cgColor
        }
    }
    
}

Then in the storyboard, go to the view that you want designable in storyboard and change it's custom class to MyPrettyDesignableView.

  1. Change it's custom class to your IBDesignable subclass: IBDesignable

  2. Set the IBInspectable properties: IBInspectable

Maintain answered 28/2, 2018 at 7:13 Comment(1)
Wow just adding the @IBDesignable solved the issue I've been having for days now. Kudos to you man. Thanks a ton for helping a newbie like me!Backstroke
P
1

Have you tried to check Automatically Refresh Views or Refresh All Views? It works in my Xcode 9.4.1.

Editor -> Automatically Refresh Views
Phytography answered 7/8, 2018 at 12:29 Comment(2)
I am using Xcode10.1, the I did exactly the same as @staticVoidMan, but the change reflecting in the storyboard is responsive for 90% of the time and not for the rest. Sometimes you do need 'Editor -> Automatically Refresh Views' to kinda trigger it or restart Xcode.Alvie
me too @infinity_coding7, some time need to be restart Xcode and clear DerivedDataPhytography
P
0

Have you checked that in Interface Builder (Editor Menu) that you have set Automatically Refresh Views and Refresh All Views?

Update: Try this:

 @IBDesignable public class CustomView: UIView {

 @IBInspectable var borderColor: UIColor = .white{
    didSet {
        layer.borderColor = borderColor.cgColor
    }
 }

 @IBInspectable var borderWidth: CGFloat = 2.0 {
    didSet {
        layer.borderWidth = borderWidth
    }
 }

 @IBInspectable var cornerRadius: CGFloat = 10.0 {
    didSet {
        layer.cornerRadius = cornerRadius
    }
 }

 @IBInspectable var shadowRadius: CGFloat {
    get {
        return layer.shadowRadius
    }
    set {
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.shadowOpacity = 0.4
        layer.shadowRadius = shadowRadius
    }

  }

override public func layoutSubviews() {
    super.layoutSubviews()
    clipsToBounds = true
   }
 }
Pet answered 28/2, 2018 at 6:18 Comment(1)
Yes i do not have the refresh all views option tho. I mean the Automatically Refresh Views option is tickedBackstroke
P
0

Please update your code as below. You must have to set layer.maskToBound = false and view.clipToBounds = false

import UIKit

extension UIView {

@IBInspectable
var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set {
        layer.cornerRadius = newValue
        layer.masksToBounds = newValue > 0
    }
}

@IBInspectable
var borderWidth: CGFloat {
    get {
        return layer.borderWidth
    }
    set {
        layer.borderWidth = newValue
    }
}

@IBInspectable
var borderColor: UIColor? {
    get {
        let color = UIColor(cgColor: layer.borderColor!)
        return color
    }
    set {
        layer.borderColor = newValue?.cgColor
    }
}

@IBInspectable
var shadowRadius: CGFloat {
    get {
        return layer.shadowRadius
    }
    set {
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.shadowOpacity = 0.4
        layer.shadowRadius = shadowRadius
        layer.maskToBounds = false
    }
}
}
Prompter answered 28/2, 2018 at 6:36 Comment(0)
S
0

Assuming you have already applied @IBDesignable correctly at the declaration of a class. And assuming you have already applied @IBInspectable at the properties of the classes, then here is the trick that worked for me.

I delete and retype @IBDesignable.

Symptomatic answered 27/5, 2021 at 22:7 Comment(0)
D
0

sometimes even after adding @IBDesignable on the class and @IBInspectable on property definition, your Xcode might not show and refresh, so first make sure you are using them correctly. if it is not refreshing in my case i had to close all instance of Xcode and restart the Xcode, then it will load the new fresh Interface builder files.

Decent answered 13/1, 2022 at 22:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.