안녕하세요.
WWDC 2021 발표를 통해, iOS 15 이상 Foundation과 SwiftUI에서 Markdown을 사용할 수 있다는 것 알고 계셨나요??
이번 글은 SwiftUI에서 markdown을 사용할 때, 고려해야 할 3가지 특이점에 대해 소개해보려고 합니다.
# 1. GFM 지원
SwiftUI는 Github Flavored Markdown(GFM)을 지원합니다.
쉽게 확인할 수 있는 예로, CommonMark에서는 지원하지 않는 취소선(문자열을 ~~로 감싼 것)이 SwiftUI에서는 사용이 가능합니다.
Text("Hello ~~world!~~")
써보니까 GFM도 지원하는 것 같은데?? 라고 추측한 것은 아니고...
Apple Developer forum에서 GFM을 지원한다고 공식적으로 답변을 주었습니다. 👍 👍
Yes, it is GitHub flavored markdown. AttributedString converts both inline and block styles. SwiftUI renders inline styles (but not images at this time). We use the fantastic cmark-gfm library to parse the markdown string.
# 2. String 변수는 markdown 사용 불가능
저희는 위에서 Text 안에 string을 넘겨서 markdown 형식으로 출력되는 것을 확인했습니다.
(정확하게는 string 변수를 넘긴 것이 아니라 string literal을 넘긴 것입니다.)
Text("**Hello**, *world!*")
그런데, string 변수를 사용하면 제대로 동작하지 않습니다.
struct ContentView: View {
let markdown = "**Hello**, *world!*"
var body: some View {
Text(markdown)
}
}
이렇게 호출해봐도 결과는 똑같아요ㅠㅠ
struct ContentView: View {
let markdown = "**Hello**, *world!*"
var body: some View {
Text("\(markdown)")
}
}
대신에, LocalizedStringKey의 init(_:)을 사용하면 정상 동작하는 것을 볼 수 있어요.
struct ContentView: View {
let markdown = "**Hello**, *world!*"
var body: some View {
Text(.init(markdown)) ✅
}
}
왜 그럴까요???
Text 뷰에 string 변수를 넘기면, localization 없이 string 변수에 있는 text를 화면에 출력합니다.
또한, Text 뷰에 string literal을 넘기면, LocalizedStringKey 생성자를 호출해서 localizedstring을 화면에 출력합니다.
(LocalizedStringKey가 ExpressibleByStringLiteral 프로토콜을 준수하니 가능한 일이겠죠??ㅎㅎ)
@frozen public struct LocalizedStringKey : Equatable, ExpressibleByStringInterpolation {
// ...
}
public protocol ExpressibleByStringInterpolation : ExpressibleByStringLiteral {
// ...
}
Text 뷰에서 마크다운 형식으로 출력하려면, LocalizedStringKey 생성자를 사용해야 하니,
string 변수를 사용하는 대신 LocalizedStringKey의 init(_:) method를 사용하는 것이죠!!! ㅎㅎㅎ
# 3. AttributedString에서 개행이 필요한 경우 MarkdownParsingOptions를 사용
AttributedString을 사용하면 markdown이 지원됩니다.
struct ContentView: View {
let attributedString = try! AttributedString(markdown: "**Hello** ~~world!~~")
var body: some View {
Text(attributedString)
}
}
하지만 개행을 넣으면, 줄 바꿈이 화면에 적용되지 않습니다.
struct ContentView: View {
let attributedString = try! AttributedString(markdown: "**Hello** ~~world!~~\nNewLine")
var body: some View {
Text(attributedString)
}
}
개행이 필요한 경우, AttributedString 초기화할 때 option으로 .inlineOnlyPreservingWhitespace를 넣어주세요.
struct ContentView: View {
let attributedString = try! AttributedString(markdown: "**Hello** ~~world!~~\nNewLine", options: .init(interpretedSyntax: .inlineOnlyPreservingWhitespace)) ✅
var body: some View {
Text(attributedString)
}
}
## 참고
- https://blog.eidinger.info/3-surprises-when-using-markdown-in-swiftui
이번 글은 여기서 마무리.
'SwiftUI' 카테고리의 다른 글
renderingMode(_:) (0) | 2022.03.01 |
---|---|
AlignmentGuide (0) | 2022.02.27 |
스크린샷 주의 팝업, 화면 녹화 방지 (3) | 2022.02.25 |
addArc(tangent1End:tangent2End:radius:) (0) | 2022.02.22 |
iOS 15에 추가된 background 관련 신규 method (0) | 2022.02.21 |