
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