0

I've been playing with the IBInspectable/IBDesignable like in this article: http://nshipster.com/ibinspectable-ibdesignable/.

It shows how you can make an extension to add extra editing options in storyboard. The problem however is that you can't see these changes reflected in the preview. For this you need to subclass, use IBDesignable and do the didset{} stuff.

The problem with this is that you need to make a subclass of every stock UIView subclass. So a subclass of UILabel, UITextField and so on. Every time you have to copy/paste the regular UIView stuff like borders and corner radius.

I don't believe Swift supports multiple inheritance, which would have made this much easier.

Let's say your IBDesignable subclass of UIView is called IBView. Is there a way to make e.g. UILabel be a subclass of IBView instead of UIView?

In the end I'm looking if there is a way to make IBDesignable less tedious.

Janneman
  • 1,093
  • 15
  • 23
  • There is no such thing as IBView as far as I know. What attributes are you trying to add to what sounds like nearly all UIKit views? For most apps you only need to subclass/extend a very small handful of UIView subclasses, as stock UIKit suffices. If what you are trying to do it have reusable IBDesigner/IBInspectable views for several projects, throw them into a framework target and declare them as **open**. IB handles that very well. –  Jan 07 '17 at 17:18
  • No, it's not possible. Use composition instead of inheritance. For example, you can create a subview of `UIView` with rounded corners and if you need rounded corners on anything else, just wrap that into the rounded view. – Sulthan Jan 07 '17 at 17:48
  • IBView is what I made up myself as the name of the subclass of UIView that has the extra IBDesignable stuff in it. Yes I am making a single file that I can reuse. So it's not that big of a deal if there isn't an easier way, but I'm just curious if there is. – Janneman Jan 07 '17 at 19:07

1 Answers1

3

Like you, I'm trying to find a better solution to work with IBDesignable.

What I did to avoid repeat the same code:

  1. I made an extension of UIView to insert all the @IBInspectables I want (like corder radius, border width...).
  2. I created my @IBDesignables that only inherit from UIView, UIButton (or any subclass of UIView I want) in order to render on Interface Builder.

Check this code:

extension UIView {

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

    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(cgColor: layer.borderColor ?? UIColor.clear.cgColor)
        }

        set {
            layer.borderColor = newValue?.cgColor
        }
    }

    @IBInspectable var borderWidth: Double {
        get {
            return Double(layer.borderWidth)
        }

        set {
            layer.borderWidth = CGFloat(newValue)
        }
    }
}

@IBDesignable
class BorderView: UIView { }

@IBDesignable
class BorderButton: UIButton { }

I hope it helps you!

Roberto Sampaio
  • 531
  • 1
  • 5
  • 15