SwiftUI에서 ViewModifier와 modifier(_:)
SwiftUI에서 ViewModifier는 뷰의 외형과 동작을 변경하거나 확장하는 데 사용하는 재사용 가능한 방법.
이를 통해 코드 중복을 줄이고, 더 읽기 쉽고 유지 관리하기 쉬운 코드를 작성할 수 있음.
1. ViewModifier란?
정의
- ViewModifier는 SwiftUI의 프로토콜로, 뷰의 외형이나 동작을 캡슐화하여 여러 뷰에 재사용할 수 있음.
- 뷰의 꾸미기 작업, 레이아웃 변경, 행동 추가 등을 위해 사용.
구조
ViewModifier는 다음과 같은 요구사항을 가진 프로토콜
- body(content:) 메서드: 원래의 뷰(content)를 기반으로 수정된 뷰를 반환.
- 원래의 뷰를 변경 시키는 것이 아니라 수정된 뷰를 반환!
- AssociatedType: Body라는 제네릭 타입을 사용하며, 반환값은 반드시 SwiftUI View.
2. ViewModifier 기본 사용법
1. ViewModifier 구현
struct HighlightModifier: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(Color.yellow)
.cornerRadius(8)
}
}
2. View에 적용
- modifier(_:) 메서드를 사용하여 적용.
struct ContentView: View {
var body: some View {
Text("Hello, SwiftUI!")
.modifier(HighlightModifier())
}
}
3. 결과

3. modifier(_:) 메서드
- modifier(_:)는 View 프로토콜의 기본 메서드.
- ViewModifier를 사용하는 뷰에 수정 사항을 적용하는 데 사용.
선언
func modifier<T>(_ modifier: T) -> some View where T : ViewModifier
특징
- 뷰의 스타일이나 동작을 동적으로 변경할 수 있음.
- 매개변수로 사용자 정의한 ViewModifier를 전달해야 함.
- 뷰에 적용된 순서에 따라 결과가 달라질 수 있음.
사용 예시
Text("Hello, World!")
.modifier(ModifierA())
.modifier(ModifierB())
- ModifierA가 먼저 적용되고, 그 위에 ModifierB가 추가로 적용.
- 수정자의 순서는 UI 결과에 직접적인 영향.
4. ViewModifier를 재사용 가능한 뷰 스타일로 사용
ViewModifier는 뷰의 스타일을 캡슐화하여 재사용성을 높일 수 있음.
사용자 정의 스타일
struct TitleStyle: ViewModifier {
func body(content: Content) -> some View {
content
.font(.largeTitle)
.foregroundColor(.blue)
}
}
간결한 호출을 위한 확장
반복적인 .modifier(TitleStyle()) 호출을 줄이기 위해 익스텐션을 사용할 수 있음.
extension View {
func titleStyle() -> some View {
self.modifier(TitleStyle())
}
}
사용 예시
Text("SwiftUI is amazing!")
.titleStyle()
5. ViewModifier의 실용적 활용
1. 조건부 스타일링
struct ConditionalModifier: ViewModifier {
var isActive: Bool
func body(content: Content) -> some View {
content
.padding()
.background(isActive ? Color.green : Color.red) // 조건 설정
.cornerRadius(10)
}
}
extension View {
func conditionalStyle(isActive: Bool) -> some View {
self.modifier(ConditionalModifier(isActive: isActive))
}
}
// 사용 예시
Text("Dynamic Styling")
.conditionalStyle(isActive: true) // 녹색 배경
2. 복합 스타일 캡슐화
struct ShadowedModifier: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(Color.white)
.cornerRadius(10)
.shadow(color: .gray, radius: 5, x: 0, y: 5)
}
}
extension View {
func shadowedStyle() -> some View {
self.modifier(ShadowedModifier())
}
}
// 사용 예시
Text("Shadowed Text")
.shadowedStyle()
6. ViewModifier와 직접 스타일링 비교
직접 스타일링 | ViewModifier 사용 | |
재사용성 | 낮음 | 높음 |
코드 중복 제거 | 반복적인 코드 작성 필요 | 중복 코드 캡슐화 가능 |
가독성 | 복잡한 뷰에서 낮아질 수 있음 | 스타일링 로직이 독립적이므로 더 명확 |
조건부 스타일링 | if-else 또는 삼항 연산자 사용 필요 | ViewModifier로 캡슐화 가능 |
예시 비교
// 직접 스타일링
Text("Hello")
.padding()
.background(Color.blue)
.cornerRadius(10)
// ViewModifier 사용
Text("Hello")
.modifier(CustomModifier())
7. ViewModifier와 환경 데이터(@Environment)
ViewModifier는 환경 데이터를 통해 뷰의 스타일을 동적으로 변경할 수도 있음.
예제: 다크 모드 감지
struct AdaptiveModifier: ViewModifier {
@Environment(\\.colorScheme) var colorScheme
func body(content: Content) -> some View {
content
.padding()
.background(colorScheme == .dark ? Color.black : Color.white)
.cornerRadius(10)
}
}
extension View {
func adaptiveStyle() -> some View {
self.modifier(AdaptiveModifier())
}
}
// 사용 예시
Text("Adaptive Modifier")
.adaptiveStyle()
8. 주의할 점
- 지나친 사용 자제
- 너무 많은 ViewModifier를 사용하면 코드 복잡도가 증가할 수 있음.
- 간단한 스타일은 일반적인 뷰 수정 체인을 사용하는 것이 더 적합할 수 있음.
- 중첩된 Modifier
- 여러 Modifier를 중첩해서 사용하면 관리가 어려워질 수 있기에 적절히 분리하여 사용하는 것이 좋음.
'SwiftUI' 카테고리의 다른 글
[SwiftUI] NavigationView vs NavigationStack (0) | 2024.05.09 |
---|---|
[SwiftUI] SwiftUI의 View Rendering (0) | 2024.05.08 |
[SwiftUI] Source of Truth (0) | 2024.04.29 |
[SwiftUI] @State와 @Binding의 projectedValue ($) (0) | 2024.04.29 |
[SwiftUI] @State, @Binding (0) | 2024.04.29 |