Search code examples
iosswiftnsattributedstring

NSAttributedString Shadow and Stroke on iOS?


When I use stroke and shadow, I get some sort of double-stroke. How can I fix this?

Playground Code:

import UIKit

var shadow = NSShadow()
shadow.shadowColor = UIColor.black
shadow.shadowOffset = CGSize(width: 0, height: 3)

class CustomLabel: UILabel {
    override func drawText(in rect: CGRect) {
        let attributes: [String: Any] = [NSStrokeWidthAttributeName: -2.0,
                          NSStrokeColorAttributeName: UIColor.black,
                          NSForegroundColorAttributeName: UIColor.white,
                          NSShadowAttributeName: shadow,
                          NSFontAttributeName: UIFont(name: "AvenirNext-Bold", size: 50)]
        self.attributedText = NSAttributedString(string: self.text ?? "", attributes: attributes)
        super.drawText(in: rect)
    }
}

let label = CustomLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
label.backgroundColor = UIColor.orange
label.text = "Hello"

Result:

enter image description here


Solution

  • I figured it out. If I apply a shadow to the label's CALayer, and disable the background-color, it works as expected:

    import UIKit
    
    class CustomLabel: UILabel {
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.layer.shadowColor = UIColor.black.cgColor
            self.layer.shadowOffset = CGSize(width: 0, height: 3)
            self.layer.shadowOpacity = 1.0
            self.layer.shadowRadius = 0.0
        }
    
        override func drawText(in rect: CGRect) {
            let attributes: [String: Any] = [NSStrokeWidthAttributeName: -2.0,
                                             NSStrokeColorAttributeName: UIColor.black,
                                             NSForegroundColorAttributeName: UIColor.white,
                                             NSFontAttributeName: UIFont(name: "AvenirNext-Bold", size: 50)]
            self.attributedText = NSAttributedString(string: self.text ?? "", attributes: attributes)
            super.drawText(in: rect)
        }
    }
    
    let label = CustomLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
    label.text = "Hello"
    

    enter image description here