Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Advanced)

0. ViewModifier/ 뷰 모디파이어

by Toughie 2023. 6. 18.

🦁ViewModifier/ 뷰 모디파이어🦁

아카데미에서 챌린지 중에 다른 팀원이 알려줘서 사용해본 적이 있는 뷰 모디파이어!

여러 커스텀을 하다보면 뷰모디파이어가 덕지덕지 붙게 되고 코드가 너무 길어져서 불-편 했었는데

이걸 많이 해소해줄 수 있는 녀석이 바로 ViewModifier이다.

 

기본적인 버튼모양을 만든다고 하면?

        Text("Toughie")
            .font(.headline)
            .foregroundColor(.white)
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .background(Color.blue)
            .cornerRadius(10)
            .shadow(radius: 10)

벌써 모디파이어가 엄청나다.. 

어떤 단점이 있을까? 우선 비슷한 버튼을 만든다고 치면 이 모디파이어들을 복붙해야한다. 그럼 코드가 또 길고 지저분해지겠지?

또한 만약 폰트나 간격 등을 일괄적으로 바꾸고 싶다면..하나씩 다 바꿔줘야 한다. '비효율적이다.'

 

이걸 ViewModifier를 통해서 깔끔하게 관리할 수 있다.

ViewModifier

struct ButtonViewModifier: ViewModifier {
    let backgroundColor: Color
    
    func body(content: Content) -> some View {
        content
            .foregroundColor(.white)
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .background(backgroundColor)
            .cornerRadius(10)
            .shadow(radius: 10)
    }
}

ViewModifier 프로토콜을 채택한 구조체를 만들어준다.

요구조건으로 body메서드를 구현해준다. content를 파라미터로, some View를 반환한다.

 

여기서 어떤 모디파이어들을 뷰모디파이어에 넣을것인가? 이건 개발자의 마음이다.

디자이너와 얘기하면 더 좋을 부분! 피그마에서 컴포넌트를 관리하는 것과 거의 동일하기 때문이다.

만약 폰트도 전부 통일되어야 하는 경우라면 폰트를 여기 추가해도 괜찮을 것이고~

 

그래서 이걸 어떻게 쓰는가?

            Text("Hello, World")
                .font(.headline)
                .modifier(ButtonViewModifier(backgroundColor: .red))

이렇게 쓸 수 있다. 만약 컬러도 한가지로 정하고 싶다면 뷰모디파이어에서 디폴트컬러를 정해주면 될 것이다.

하지만 이러면 확장성이 너무 떨어지는 문제가 있다.

 

좀 더 기깔나게 쓰는 방법.

extension으로 메서드를 구현해서 사용할 수 있다.

extension View {
    
    func modifyToDefaultButton(backgroundColor: Color = .blue) -> some View {
        self.modifier(ButtonViewModifier(backgroundColor: backgroundColor))
    }
}

default parameter로 .blue를 설정해 주었다. 즉 따로 인수를 전달하지 않으면 파란색!

이제 이걸 다음과 같이 사용할 수 있다.

            Text("Hello, Toughie")
                .font(.subheadline)
                .modifyToDefaultButton(backgroundColor: .green)
                
            Text("Hello, Toughie")
                .font(.largeTitle)
                .modifyToDefaultButton()

 

+ extension을 활용해서 컬러 편하게 사용하기

extension Color {

    static let myColor1 = Color(#colorLiteral(red: 1, green: 0.6986920238, blue: 0.6761365533, alpha: 1))
    static let myColor2 = Color(#colorLiteral(red: 0.692043066, green: 0.9036079049, blue: 1, alpha: 1))
}

extension은 타입에 대한 추가 기능을 제공하는 것이기 때문에 

타입에 함수, 타입 프로퍼티, 서브스크립트, 생성자 등을 추가할 수 있다. (stored Property는 불가능!)

이렇게 컬러를 extension에서 타입 프로퍼티로 구현해주면 아래와 같이 편리하게 사용할 수 있다.

            Text("COLOR EXTENSION")
                .modifyToDefaultButton(backgroundColor: Color.myColor1)

나는 이렇게 깔끔하게 코드를 정리할 수 있는 기법들이 너무 좋다..