はじめに
「影をつけてほしい」とよく言われますが、どんな影を望んでいるか、比較できるものを見せないと意思疎通が難しい...🤔
そういう経験を度々するので、iOSで文字に影をつける方法の比較記事を作ってみました。
まとめると、影の主張の強さは、UILabel#shadow > NSShadow > CALayer の順です。

実装コストは、基本的には、UILabel#shadow < CALayer < NSShadow の順に安いです。
以下では、各実装方法と特徴を整理します。
UILabel#shadowColor

ぼやっとした影ではなく、直線的な影です。
UILabelのshadowColor/shadowOffsetを指定する方法です。InterfaceBuilderのshadowプロパティはこの値を指定するものです。
サンプルはoffsetとして{2,2}を指定しているため、右下にズレた影がついています。
とにかく実装が簡単なのが魅力です。
NSShadow

よりぼんやりとした影です。後述のCALayerの方法よりもはっきりと影がつきます。白文字のときにこのような黒影を敷くと、白い背景のときに視認性が良くなります。
NSAttributedStringの属性として指定するため、3つの方法のなかでは最も扱いずらいです。
@IBInspectable
のプロパティを作ってAttributedStringに属性を追加するサブクラスを作って使うと、IB上で値を指定できて便利ですね。
import UIKit
@IBDesignable class ShadowAttributeSettableLabel : UILabel {
@IBInspectable var shadowColorForCustom: UIColor = .clear
@IBInspectable var shadowOffsetForCustom: CGSize = .zero
@IBInspectable var shadowRadiusForCustom: CGFloat = 0.0
override func layoutSubviews() {
super.layoutSubviews()
guard let text = text, let attributed = attributedText else { return }
let mutable = NSMutableAttributedString(attributedString: attributed)
let shadow = createShadow()
let range = NSRange(location: 0, length: text.count)
mutable.addAttribute(.shadow, value: shadow, range: range)
attributedText = mutable
}
private func createShadow() -> NSShadow {
let shadow = NSShadow()
shadow.shadowColor = shadowColorForCustom
shadow.shadowOffset = shadowOffsetForCustom
shadow.shadowBlurRadius = shadowRadiusForCustom
return shadow
}
}
CALayer

最もぼんやりした影です。
CoreAnimationのCALayerのlayer.shadowColor/shadowOffset/shadowRadius/shadowOpacityを指定する方法です。
layer.shadowColor以外の値はIBのkeypathで指定できます。ColorはUIColorの値になるため、layer.shadowColorはコードでセットする必要があります。ですので、 @IBInspectable
のプロパティを増やしたサブクラスを作らないとIBで指定できません。
import UIKit
@IBDesignable class ShadowUIColorSettableLabel : UILabel {
@IBInspectable var shadowUIColor: UIColor = .clear {
didSet {
layer.shadowColor = shadowUIColor.cgColor
}
}
}
画像サンプルは、shadowOpacityを0.3とし、色のアルファを1にしたものです。shadowOpacityを1とし、アルファを0.3としたものと同じ仕上がりになるようです。
おまけ: 全部やると?

別次元の三つの影が一緒に現れた絵になります。
邪悪な感じがしますね。
今回のコード
CompareShadows
https://github.com/hsylife/CompareShadows