Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you add IBDesignable properties to UIView using categories/extensions?

For those that don't know what I'm talking about, Xcode 6.0 added new features, IBDesignable and IBInspectable.

When you tag your custom views with IBInspectable properties, those properties show up in the Attributes Inspector in IB.

Likewise, when you tag a custom UIView subclass with IBDesignable, Xcode compiles your views and invokes the code to render your view objects right in the Xcode window so you can see what they look like.

The technique for adding IBDesignable and IBInspectable attributes to custom views is pretty much identical in Swift and Objective-C. IBInspectable properties appear in the Interface Builder Attributes Inspector regardless of which language you use to define them.

I've created a category of UIView in Objective-C and an extension of UIView in Swift that promote the borderWidth, cornerRadius, borderColor, and layerBackgroundColor properties of the view's underlying layer as properties of the view. If you change the property, the extension/category does type conversion as required and forwards the change to the layer.

The IBInspectable part works great. I see and can set the new properties in the IB attributes inspector.

I could have sworn that last week, the IBDesignable attribute on my view category/extension was working too, and I could see my custom UIView category rendering in IB with it's changed layer attributes. This week it isn't working.

Was I hallucinating?

Can categories/extensions of existing system classes draw their custom UI in Interface Builder when they are set up with IBDesignable?

like image 817
Duncan C Avatar asked Apr 27 '15 22:04

Duncan C


2 Answers

Since posting this question I've learned that @IBDesignable does not work for class extensions. You can add the tag, but it has no effect.

like image 89
Duncan C Avatar answered Nov 13 '22 23:11

Duncan C


I was able to make it work with code below, but the side effect is that some times IB agent in storyboard crashes because it has to refresh too many UI elements. Restarting Xcode fixes problem temporarily until next crash. Maybe that's the problem OP is facing

@IBDesignable
extension UIView
{

    @IBInspectable
    public var cornerRadius: CGFloat
    {
        set (radius) {
            self.layer.cornerRadius = radius
            self.layer.masksToBounds = radius > 0
        }

        get {
            return self.layer.cornerRadius
        }
    }

    @IBInspectable
    public var borderWidth: CGFloat
    {
        set (borderWidth) {
            self.layer.borderWidth = borderWidth
        }

        get {
            return self.layer.borderWidth
        }
    }

    @IBInspectable
    public var borderColor:UIColor?
    {
        set (color) {
            self.layer.borderColor = color?.cgColor
        }

        get {
            if let color = self.layer.borderColor
            {
                return UIColor(cgColor: color)
            } else {
                return nil
            }
        }
    }
}

That's why I am trying to add where clause to reduce subclasses which should extend this functionality: Generic IBDesginables UIView extension

like image 8
Paulius Vindzigelskis Avatar answered Nov 13 '22 21:11

Paulius Vindzigelskis