My thoughts
UIView를 사용해서 UILabel을 감싸는 컨테이너를 만들어 사용했습니다. 그런데 UIStackView나 UIView 등 또 한번 이상 감싸고 있는 상위 컴포넌트가 존재할 때 depth가 깊어지면서 화면의 복잡도가 증가하면서 발생하는 문제가 있었습니다:
- 예측하지 못한 레이아웃 충돌 문제 증가
- 레이아웃 디버깅으로 소요되는 시간 증가
- 제약조건 코드의 양 증가
UILabel 클래스에는 padding을 포함한 여백 값을 조절할 수 있는 기능을 지원하고 있지 않아서 별도의 서브 클래스를 제작해야 했습니다.
Programmatic UI 시
class PaddableLabel: UILabel { fileprivate var leftInset: CGFloat fileprivate var rightInset: CGFloat fileprivate var topInset: CGFloat fileprivate var bottomInset: CGFloat required init(edgeInsets left: CGFloat, _ right: CGFloat, _ top: CGFloat, _ bottom: CGFloat) { self.topInset = top self.leftInset = left self.bottomInset = bottom self.rightInset = right super.init(frame: .zero) } @available(*, unavailable) required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func drawText(in rect: CGRect) { let edgeInsets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset) super.drawText(in: rect.inset(by: edgeInsets)) } override var intrinsicContentSize: CGSize { var contentSize = super.intrinsicContentSize contentSize.width += leftInset + rightInset contentSize.height += topInset + bottomInset return contentSize } }
Storyboard 사용 시
Storyboard의 경우 Attributes Inspector에서 직접 값을 조정할 수 있도록
@IBInspectable
어트리뷰트를 채택했습니다. Interface Builder로 쉽게 사용이 가능하다는 것을 알 수 있습니다.class PaddableLabel: UILabel { var padding: UIEdgeInsets @IBInspectable var left: CGFloat { get { padding.left } set { padding.left = newValue } } @IBInspectable var right: CGFloat { get { padding.right } set { padding.right = newValue } } @IBInspectable var top: CGFloat { get { padding.top } set { padding.top = newValue } } @IBInspectable var bottom: CGFloat { get { padding.bottom } set { padding.bottom = newValue } } override init(frame: CGRect) { self.padding = .zero super.init(frame: frame) } required init?(coder: NSCoder) { self.padding = .zero super.init(coder: coder) } override func drawText(in rect: CGRect) { super.drawText(in: rect.inset(by: padding)) } convenience init(inset: UIEdgeInsets) { self.init(frame: .zero) self.padding = inset } override var intrinsicContentSize: CGSize { var contentSize = super.intrinsicContentSize contentSize.width += padding.left + padding.right contentSize.height += padding.top + padding.bottom return contentSize } }
패딩 값을 직접 조절할 수 있는 UILabel을 사용하니 이전에 겪었던 문제들을 다시 겪을 필요가 없어졌고, 추가적인 기능이 필요하면 나중에 쉽게 해당 서브 클래스 추가하면 된다는 장점이 있었습니다.
Share article