Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
Tags
- UICollectionView
- 애니메이션
- Protocol
- tableView
- RxCocoa
- MVVM
- Refactoring
- rxswift
- Human interface guide
- ios
- HIG
- map
- swift documentation
- scrollview
- uitableview
- 리팩토링
- collectionview
- combine
- 리펙토링
- ribs
- Clean Code
- UITextView
- swiftUI
- uiscrollview
- 스위프트
- 클린 코드
- SWIFT
- Observable
- Xcode
- clean architecture
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - SwiftUI] 한글 개행 처리 방법, 한글 글자 단위 개행 방법 (linebreak, byCharWrapping 적용 방법, byWordWrapping) 본문
iOS 응용 (SwiftUI)
[iOS - SwiftUI] 한글 개행 처리 방법, 한글 글자 단위 개행 방법 (linebreak, byCharWrapping 적용 방법, byWordWrapping)
jake-kim 2025. 4. 23. 01:28Text 컴포넌트의 디폴트 개행 처리 방식
- SwiftUI의 Text의 디폴트 개행 방식은 띄어쓰기 단위로 개행
struct ContentView: View {
var body: some View {
VStack {
// 문구 출처: https://ko.wikipedia.org/wiki/%EC%95%A0%ED%94%8C
Text("애플(영어: Apple Inc.)은 미국 캘리포니아의 아이폰, 아이패드, 애플 워치, 에어팟, 아이맥, 맥북, 맥 스튜디오와 맥 프로, 홈팟, 비전 프로, 에어태그 등의 하드웨어와 그 제품들의 iOS, iPadOS, Watch OS, macOS, Vision OS, TV OS 등의 소프트웨어를 설계, 디자인하는 기업이다. 2011년부터 팀 쿡이 CEO를 맡고 있다. 또한 그 소프트웨어에 애플 앱 스토어, 뮤직, 뉴스, 아케이드, tv, 피트니스, 페이, 저장 클라우드 등의 서비스를 제공한다.")
}
}
}

- 이것은 UIKit의 UILabel에 lineBreakMode 디폴트 값인 `byWordWrapping`와 동일
- (UILabel의 lineBreakMode 참고)
=public enum NSLineBreakMode : Int, @unchecked Sendable {
case byWordWrapping = 0 // Wrap at word boundaries, default
case byCharWrapping = 1 // Wrap at character boundaries
case byClipping = 2 // Simply clip
case byTruncatingHead = 3 // Truncate at head of line: "...wxyz"
case byTruncatingTail = 4 // Truncate at tail of line: "abcd..."
case byTruncatingMiddle = 5 // Truncate middle of line: "ab...yz"
}
- 여기서 byCharWrapping같이 문자 하나를 기준으로 개행을 하고자 한다면 SwiftUI에서는 해당 옵션이 없기 때문에 별도 구현 필요
(byCharWrapping)

SwiftUI에서 byCharWrapping 구현 방법
- UIViewRepresentable을 활용하여 UILabel을 SwiftUI에서도 쓸 수 있게끔 만드는 방법이 있지만, 수정양이 많은 단점이 있으므로 다른 방법 사용하기
- \u{200B} 문자 사용하기
- \u{200B} 문자 특성상 width가 0인 문자인데, 이 문자들을 기존 문자들 뒤에 삽입
- 이 문자는 개행을 할 수 있는 기준이 되므로 iOS 내부에서 이 문자를 만났을 때 frame의 width에 도달한다면 바로 개행 시킬 것
- 곧 기존 문자 바로 뒤에 이 문자가 붙으므로써 개행의 기준이 단어 단위로 바뀐 것
- extension으로 기존문자들 사이에 이 문자를 삽입
extension String {
var byCharWrapping: Self {
map(String.init).joined(separator: "\u{200B}")
}
}
- 사용하는쪽에서는 아래 처럼 사용하기만 하면 byCharWrapping 완성
Text(sampleText.byCharWrapping)

- 전체 코드
import UIKit
import SwiftUI
struct ContentView: View {
let sampleText = "애플(영어: Apple Inc.)은 미국 캘리포니아의 아이폰, 아이패드, 애플 워치, 에어팟, 아이맥, 맥북, 맥 스튜디오와 맥 프로, 홈팟, 비전 프로, 에어태그 등의 하드웨어와 그 제품들의 iOS, iPadOS, Watch OS, macOS, Vision OS, TV OS 등의 소프트웨어를 설계, 디자인하는 기업이다. 2011년부터 팀 쿡이 CEO를 맡고 있다. 또한 그 소프트웨어에 애플 앱 스토어, 뮤직, 뉴스, 아케이드, tv, 피트니스, 페이, 저장 클라우드 등의 서비스를 제공한다."
var body: some View {
VStack {
Text(sampleText.byCharWrapping)
Spacer()
.frame(height: 30)
LabelView(text: sampleText)
}
}
}
extension String {
var byCharWrapping: Self {
map(String.init).joined(separator: "\u{200B}")
}
}
struct LabelView: View {
var text: String
@State private var height: CGFloat = .zero
var body: some View {
InternalLabelView(text: text, dynamicHeight: $height)
.frame(minHeight: height)
}
struct InternalLabelView: UIViewRepresentable {
var text: String
@Binding var dynamicHeight: CGFloat
func makeUIView(context: Context) -> UILabel {
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byCharWrapping
return label
}
func updateUIView(_ uiView: UILabel, context: Context) {
uiView.text = text
DispatchQueue.main.async {
dynamicHeight = uiView.sizeThatFits(CGSize(width: uiView.bounds.width, height: CGFloat.greatestFiniteMagnitude)).height
}
}
}
}
#Preview {
ContentView()
}
* 참고
- https://ko.wikipedia.org/wiki/%EC%95%A0%ED%94%8C
- https://chatgpt.com/c/68049c4f-b2b0-8011-af7e-4e447015bdf0
'iOS 응용 (SwiftUI)' 카테고리의 다른 글
Comments
