MINRYUL
류링류링
MINRYUL
전체 방문자
오늘
어제
  • 분류 전체보기
    • Swift
      • 학습
    • iOS
      • Toy-Project
      • 학습
      • Metal
    • CS
    • TIL

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • WWDC
  • METAL
  • Existential type
  • CollectionView Cell
  • demangle
  • ios
  • TableView Cell
  • Clean Architecture
  • some
  • Custom Calendar
  • Existential any
  • BDD
  • Any
  • ViewStore
  • opaque type
  • urlsession
  • dynamic frameworkm
  • tuist
  • collectionView
  • RxCocoa
  • WWDC 2024
  • configuration_bulid_dir
  • RxSwift
  • Protocol
  • TDD
  • Swift
  • static framework
  • RxTest
  • AttributeText
  • RxNimble

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
MINRYUL

류링류링

iOS/학습

SwiftUI) iOS13 부터 지원하는 간단한 커스텀 Attribute Text 만들기

2023. 2. 15. 21:00

 SwiftUI에서는 attributeText를 iOS15부터 지원한다. 따라서 그 이전 버젼은 UIViewRepresentable을 사용해서 커스텀 하거나, Text() + Text() 형식으로 AttributeText를 만든다. 그 중 두번째 방법을 사용해서 간단한 커스텀 AttributeText를 만들어보자. UIViewRepresentable를 사용해서 커스텀 하려니 스유 개초보라 만들어진 View가 제대로 크기를 못잡고 지 맘대로 크기를 잡더라..

(비효율적인 코드를 작성했을 수도 있음.)

 attribute를 사용하는 화면마다 Text() + Text() 하기는 너무 비효율적이니, String의 extension으로 함수를 만들어 전체 String에서 특정 텍스트를 바꿀 수 있도록 해보겠음. 그러기 위해 Attribute 속성을 만들기 위한 Protocol을 선언해주겠음.

protocol StringAttributeProtocol {
  var weight: Font.Weight { get }
  var size: CGFloat { get }
  var color: Color { get }
}

이 프로토콜은 현재 텍스트가 가지고 있는 font와 color를 받는다. 그리고,

public struct BaseAttribute: StringAttributeProtocol {
  let weight: Font.Weight
  let size: CGFloat
  let color: Color
  
  public init(weight: Font.Weight, size: CGFloat, color: Color) {
    self.weight = weight
    self.size = size
    self.color = color
  }
}

public struct StringAttribute: StringAttributeProtocol {
  let text: String
  let weight: Font.Weight
  let size: CGFloat
  let color: Color
  
  public init(text: String, weight: Font.Weight, size: CGFloat, color: Color) {
    self.text = text
    self.weight = weight
    self.size = size
    self.color = color
  }
}

 실제로 값을 받을 수 있도록 프로토콜을 채택한 구현체를 2개 만들어 줬다, 첫번째는 전체 Text에 대한 정보고, 두번째 구현체는 특정 텍스트에 Attribute를 부여할 정보다.

 

그럼 준비는 다 되었으니 Text를 만들어줄 String extension 함수를 만들어보자.

extension String {
  public func toAttributesText(
    base: BaseAttribute,
    _ attribute: StringAttribute
  ) -> Text {
      var text = Text("")
	let parsingStr = self.components(separatedBy: attribute.text)
        
      parsingStr.enumerated().forEach { index, str in
        let appendText = self._makeAttributeText(text: str, attribute: base)
        text = text + appendText
          
        if index == (parsingStr.count - 1) { return }
          
        let attributeText = self._makeAttributeText(
          text: attribute.text,
          attribute: attribute
        )
          
        text = text + attributeText
      }
      
      return text
  }
  
  private func _makeAttributeText(
    text: String, attribute: StringAttributeProtocol
  ) -> Text {
    return Text(text)
      .font(.system(size: attribute.size, weight: attribute.weight))
      .foregroundColor(attribute.color)
  }
}

 첫번째 파라미터로 전체 텍스트에 대한 정보를 받아주고, 두번째 파라미터로 attribute로 바꿀 텍스트의 정보를 받았다. 그리고, 전체 텍스트에서 특정 텍스트를 기준으로 나눠주고, 잘린 텍스트를 기준으로 _makeAttributeText라는 함수를 통해 전체 String의 Text와 잘린 String의 Text를 만들어 하나씩 붙여준다. 

 

 반복문을 돌아 모든 정보가 더해진 Text를 리턴하면 원하는 특정 텍스트에만 폰트, 색상이 변경된다.

'iOS > 학습' 카테고리의 다른 글

[iOS] 푸시, 다이나믹 링크 등으로 실행될 때 디버깅하기  (0) 2023.08.28
Error) failed to demangle superclass of ‘…’ from mangled name ‘…’  (3) 2023.05.03
TCA) Store vs ViewStore  (0) 2023.02.13
Storyboard 에서 Generic Type 의존성 주입하기 2  (0) 2022.08.29
Custom Horizontal FlowLayout  (0) 2022.06.21
    'iOS/학습' 카테고리의 다른 글
    • [iOS] 푸시, 다이나믹 링크 등으로 실행될 때 디버깅하기
    • Error) failed to demangle superclass of ‘…’ from mangled name ‘…’
    • TCA) Store vs ViewStore
    • Storyboard 에서 Generic Type 의존성 주입하기 2
    MINRYUL
    MINRYUL
    열심히 살자

    티스토리툴바