[SwiftUI] ViewModifier에 대해

Ted·2023년 12월 1일
0

SwiftUI

목록 보기
5/5

자자... 구조체 천국인 SwiftUI에서 어떤 View를 꾸미는 그런 것들을 캡슐화해서 구성가능한 방법이 있다는 것을 알았다.

바로 그건 'ViewModifier' !!!



Viewmodifier가 뭔데?

SwiftUI의 선언형 구문의 핵심이기도한 ViewModifier를 자세하게 알아보자

ViewModifier에는 Content라는 매개변수를 사용하는 body가 필수적으로 있어야한다.
여기서 Content는 수정자가 적용되는 일종의 보기를 나타낸다.

struct CustomModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .foregroundColor(.blue)
            .font(.headline)
            .padding()
    }
}

이 코드를 보면 특정 색을 바꾸고 폰트를 바꾸고 패딩을 추가하는 코드다. 보통 Text에 수정자로 들어가는 코드이다.



애플 공식 문서에 따르면 ViewModifier 프로토콜을 통해서 모든 뷰에 재사용 가능한 수정자를 생성할 수 있다고 한다.

해당 인스턴스 메소드 func body에 대해 자세하게 보면 호출하는 content를 가져오는 것이다.

@ViewBuilder @MainActor
func body(content: Self.Content) -> Self.Body

ViewModifier는 추가적으로 View에 애니메이션을 추가하는 animation(_ :)

func animation(_ animation: Animation?) -> some ViewModifier

과 self와 연결된 새 수정자를 반환하는 concat(_ :)도 있다.

func concat<T>(_ modifier: T) -> ModifiedContent<Self, T>

따라서 다음과 같은 코드를 사용하면 modifier(_:)를 통해서 적용하는 방식보다 일반적으로 자체 확장을 통해 사용이 가능하다.


Text("Downtown Bus")
    .modifier(CustomModifier())


extension View {
    func borderedCaption() -> some View {
        modifier(CustomModifier())
    }
}

Image(systemName: "bus")
    .resizable()
    .frame(width:50, height:50)
Text("Downtown Bus")
    .borderedCaption()

또한 ViewModifier의 경우 여러 개의 ViewModifier를 결합하여 사용도 가능하다.

struct CombinedModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .modifier(CustomModifier())
            .padding()
            .background(Color.gray)
    }
}

만약 어떤 변수나 상태 타입을 통해 조건에 따라 수정하고 싶은 부분이 있다면 다음과 같이 적용할 수도 있다.

struct ConditionalModifier: ViewModifier {
    let condition: Bool

    func body(content: Content) -> some View {
        if condition {
            return content
                .foregroundColor(.green)
        } else {
            return content
                .foregroundColor(.red)
        }
    }
}

 


근데 여기서 문제 발생!

TopBar를 만들고 해당 TopBar에 버튼을 누르면 해당 버튼의 이름을 text로 가지는 토스트가 아래에 뜨게 하는 것을 구현하고 싶었다.
업로드중..
NavigationTopBar를 Modifier를 통해서 간결하게 만들고자 했던 내 코드에서 뭔가 ToolbarItem이외에 다른 요소를 붙이고자 하면

Static method 'buildExpression' requires that 'ToolbarItem<(), DoubleTitleBar>' conform to 'View'

라는 에러가 계속 발생한다. 이를 직역하면 buildExpression을 사용하고자하면 해당 ToolbarItem<(), DoubleTitleBar>가 View를 따라야한다는 의미이고 이는 순서가 잘못됐다는 의미이다.

아래의 ydsToast도 ViewModifier로 만들어진 것이기에 여러개 중복이 가능해서 상관없다 생각했는데 이런 문제가 발생했다. 이를 해결하려면 Non-View Type이 아닌 정확한 ViewType만을 반환하게 해줘야하는 것이다.

만약 수정해서 Toast를 띄우는 것이 성공하게 된다면 글을 수정해서 다시 올려보려고한다!

 






결론

결론적으로, ViewModifier는 뷰 수정자체를 캡슐화하고 코드의 재사용을 촉진하기때문에 SwiftUI의 코드 가독성을 향상시켜줄 뿐만 아니라 선언적 구문에 대한 유연한 방법을 제공해준다.

이런 ViewModifier가 많아진다면 처리하는데 불편함이 생길 수 있지만 개발자가 어떻게 이를 분리해놓고 관리하냐에 따라서 코드 유용성과 유지보수에는 엄청난 이득을 가져와줄 것같다. 또한 코드의 가독성이 한껏 올라갈 것같다.

참고자료


[뷰의 우선순위 및 개념] : https://developer.apple.com/documentation/swiftui/configuring-views
[ViewModifier] : https://developer.apple.com/documentation/swiftui/viewmodifier

profile
iOS Developer

0개의 댓글