Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView Shadow using User Defined Runtime Attributes

I'm having a hard time getting a drop shadow to show when I am using "User Defined Runtime Attributes".

It seems to work completely fine if I use code, as follows.

func formatView(view: UIView, cornerRadius: Bool) {

    if (cornerRadius) {view.layer.cornerRadius = 12 }
    view.layer.shadowColor = UIColor.black.cgColor
    view.layer.shadowOffset = CGSize.zero
    view.layer.shadowRadius = 3
    view.layer.shadowOpacity = 0.3
}

But when I try it with User Defined Runtime Attributes it doesn't show anymore. These are the ones I'm currently using.

enter image description here

The only thing that is weird is if I remove the layer.shadowColor attribute, then it seems to work again. But I can no longer control the color. It seems to default to black, but if I ever decide to choose a grey color instead, I wouldn't be able to change it.

Is this because the Color Attribute is a UIColor and shadowColor expects a CGColor?

like image 709
Jason Brady Avatar asked Sep 21 '16 22:09

Jason Brady


People also ask

How do I use user defined runtime attributes in Xcode?

You tell it the name of the property you want to change then specify the type of the property and finally the value. The user-defined runtime attributes feature limits the type of properties that can be changed to Boolean, NSNumber, NSString, CGPoint, CGSize, CGRect, NSRange, and UIColor.


1 Answers

It is indeed as you stated because the Color type in the User Defined Runtime Attributes panel creates a UIColor, but layer.borderColor holds a cgColor type.

You could solve this by creating a category that allows a proxy color to be set through Interface Builder:

extension CALayer {
    var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.cgColor
        }

        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}

But a much nicer way is to use IBDesignable instead of User Defined Runtime Attributes, it is more clear.

You do this by adding a new swift file named UIViewExtentions.swift in your project (or just paste this in any file) :

import UIKit

@IBDesignable extension UIView {
    @IBInspectable var borderColor:UIColor? {
        set {
            layer.borderColor = newValue!.cgColor
        }
        get {
            if let color = layer.borderColor {
                return UIColor(cgColor:color)
            }
            else {
                return nil
            }
        }
    }
    @IBInspectable var borderWidth:CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius:CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}

Then this will be available in Interface Builder for every button, imageView, label, etc. in the Utilities Panel > Attributes Inspector:

enter image description here

Now if you set you values in the Attributes Inspector and look back at the User Defined Runtime Attributes, you'll see they are automatically filed out for you!

EDIT: For more, see: http://nshipster.com/ibinspectable-ibdesignable/

like image 169
jo.On Avatar answered Sep 18 '22 14:09

jo.On