ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift UILabel 텍스트 부분 색상/폰트/볼드/밑줄 적용하기
    🧑‍💻/Swift 2023. 3. 1. 18:30
    반응형

    개발하다 보면 특정 부분에 볼드되거나 색상 변경, 밑줄이 들어가는 경우가 종종 있습니다.

    공통적으로 사용할 수 있기 때문에 UILabel을 extension하여 구현해 두면 요긴하게 쓸 수 있죠!

    위 예시를 보면 "지날 달 보러가기" 는 밑줄을,
    "감정 카드 저장을 원하시면 설정에서 사진 접근을 허용하세요." 는 부분 볼드 처리를 해야합니다.

     

    각 함수를 구현하기 전 개념을 짚고 넘어가 봅시다~

     

    개념 이해하기

    부분 적용을 위해서는 UILabel의 attributedText를 설정해야합니다.
    아래 코드는 UIKit.UILabel을 발췌했습니다.
    attributedText의 주석을 보시면 'attributedText 지정 시 text, font, textColor 등 모든 속성이 무시된다' 고 하네요.

    import Foundation
    
    //
    //  UILabel.h
    //  UIKit
    //
    //  Copyright (c) 2006-2018 Apple Inc. All rights reserved.
    //
    
    @available(iOS 2.0, *)
    @MainActor open class UILabel : UIView, NSCoding, UIContentSizeCategoryAdjusting {
    
        
        open var text: String? // default is nil
    
        open var font: UIFont! // default is nil (system font 17 plain)
    
        open var textColor: UIColor! // default is labelColor
    
        open var shadowColor: UIColor? // default is nil (no shadow)
    
        open var shadowOffset: CGSize // default is CGSizeMake(0, -1) -- a top shadow
    
        open var textAlignment: NSTextAlignment // default is NSTextAlignmentNatural (before iOS 9, the default was NSTextAlignmentLeft)
    
        open var lineBreakMode: NSLineBreakMode // default is NSLineBreakByTruncatingTail. used for single and multiple lines of text
    
        
        // the underlying attributed string drawn by the label, if set, the label ignores the properties above.
        @available(iOS 6.0, *)
        @NSCopying open var attributedText: NSAttributedString? // default is nil

     

     

    UILabel text를 AttributedString으로 변환하기

    그렇다면 attributedText를 지정하면 그 전에 내가 설정한 모든 속성 값이 초기화 된다는 말인데...
    초기화 되는 문제를 미연에 방지하기 위해
    내가 설정한 text와 font를 attributedString으로 바꾸어 주는 함수를 추가했습니다.

    import UIKit
    
    extension UILabel {
        /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */
        private func mutableAttributedString() -> NSMutableAttributedString? {
            guard let labelText = self.text, let labelFont = self.font else { return nil }
            
            var attributedString: NSMutableAttributedString?
            if let attributedText = self.attributedText {
                attributedString = attributedText.mutableCopy() as? NSMutableAttributedString
            } else {
                attributedString = NSMutableAttributedString(string: labelText,
                                                             attributes: [NSAttributedString.Key.font :labelFont])
            }
            
            return attributedString
        }
    }

    더 많은 NSAttributedString.key를 보고 싶다면 공식 문서를 참고해주세요.

     

     

     

    UILabel 특정 부분 Color 지정하기

    color 지정은 UILabel.textColor로 지정할 수 있지만 부분 컬러를 지정하기 위해 NSRange 타입을 parameter로 받았습니다.
    먼저 attributedString으로 변환한 뒤 NSAttributedString.key.foregroundColor를 해당 범위만큼만 다른 색상으로 대체합니다.

    extension UILabel {
        /* 텍스트 구간 색상 변경 */
        func setTextColor(_ color: UIColor, range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
            self.attributedText = attributedString
        }
        
        /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */
        private func mutableAttributedString() -> NSMutableAttributedString? {
            guard let labelText = self.text, let labelFont = self.font else { return nil }
            
            var attributedString: NSMutableAttributedString?
            if let attributedText = self.attributedText {
                attributedString = attributedText.mutableCopy() as? NSMutableAttributedString
            } else {
                attributedString = NSMutableAttributedString(string: labelText,
                                                             attributes: [NSAttributedString.Key.font :labelFont])
            }
            
            return attributedString
        }
    }

     

     

     

    UILabel 특정 부분 Font 지정하기

    Color 지정과 유사하게, NSAttributedString.key.font를 적용합니다.

    extension UILabel {    
        /* 텍스트 구간 폰트 변경 */
        func setFont(_ font: UIFont, range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range)
            self.attributedText = attributedString
        }
        
        /* 텍스트 구간 볼드 폰트 변경 */
        func setBoldFont(_ boldFontName: String, range: NSRange) {
            guard let font = self.font,
                  let boldFont = UIFont(name: boldFontName, size: font.pointSize) else {
                return
            }
            
            return setFont(boldFont, range: range)
        }
        
        /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */
        private func mutableAttributedString() -> NSMutableAttributedString? {
            guard let labelText = self.text, let labelFont = self.font else { return nil }
            
            var attributedString: NSMutableAttributedString?
            if let attributedText = self.attributedText {
                attributedString = attributedText.mutableCopy() as? NSMutableAttributedString
            } else {
                attributedString = NSMutableAttributedString(string: labelText,
                                                             attributes: [NSAttributedString.Key.font :labelFont])
            }
            
            return attributedString
        }
    }

     

     

     

    UILabel 특정 부분 밑줄(Underline) 지정하기

    NSAttributedString.key.underlineStyle로 밑줄을 적용합니다.
    NSUnderlineStyle의 rawValue (int)를 넣어주면 됩니다.

    extension UILabel {    
        /* 밑줄 추가 */
        func setUnderline(range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range)
            self.attributedText = attributedString
        }
        
        /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */
        private func mutableAttributedString() -> NSMutableAttributedString? {
            guard let labelText = self.text, let labelFont = self.font else { return nil }
            
            var attributedString: NSMutableAttributedString?
            if let attributedText = self.attributedText {
                attributedString = attributedText.mutableCopy() as? NSMutableAttributedString
            } else {
                attributedString = NSMutableAttributedString(string: labelText,
                                                             attributes: [NSAttributedString.Key.font :labelFont])
            }
            
            return attributedString
        }
    }

    사용할 때는 UIButton의 titleLabel인 경우 아래와 같이 전체 밑줄을 줄 수 있습니다.

    btnLastMonth.titleLabel?.setUnderline(range: NSRange(location: 0, length: btnLastMonth.currentTitle?.count ?? 0))

     

     

     

    전체 코드

    import UIKit
    
    extension UILabel {
        /* 텍스트 구간 색상 변경 */
        func setTextColor(_ color: UIColor, range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
            self.attributedText = attributedString
        }
        
        /* 텍스트 구간 볼드 폰트 변경 */
        func setBoldFont(_ boldFontName: String, range: NSRange) {
            guard let font = self.font,
                  let boldFont = UIFont(name: boldFontName, size: font.pointSize) else {
                return
            }
            
            return setFont(boldFont, range: range)
        }
        
        /* 텍스트 구간 폰트 변경 */
        func setFont(_ font: UIFont, range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range)
            self.attributedText = attributedString
        }
        
        /* 밑줄 추가 */
        func setUnderline(range: NSRange) {
            guard let attributedString = self.mutableAttributedString() else { return }
            
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range)
            self.attributedText = attributedString
        }
        
        /* AttributedString이 설정되어있지 않으면 생성하여 반환한다. */
        private func mutableAttributedString() -> NSMutableAttributedString? {
            guard let labelText = self.text, let labelFont = self.font else { return nil }
            
            var attributedString: NSMutableAttributedString?
            if let attributedText = self.attributedText {
                attributedString = attributedText.mutableCopy() as? NSMutableAttributedString
            } else {
                attributedString = NSMutableAttributedString(string: labelText,
                                                             attributes: [NSAttributedString.Key.font :labelFont])
            }
            
            return attributedString
        }
    }

     

     

    출처 : iOS App MyLittleUniverse

    반응형

    댓글

Designed by Tistory.