2021년 1월 3일 일요일

SwiftUI - ViewModifier 다루기

 ViewModifier는

뷰나 뷰에 적용된 다른 수식어에 적용해서, 어떠한 변화를 준 후 View를 반환하는 역할을 수행하도록 하는 Protocol입니다! 

 

요런거 많이 보셨죠? 이런게 Modifier, 수식어입니다. 

오늘은 ViewModifier 프로토콜을 이용해서 커스텀 수식어를 만들어 보겠습니다! 

 

 


예를 들어서,  요로코롬 생긴 Text를 만들기 위해서 우리는 아래와 같이 수식어를 적용합니다.

 

 

이러한 형식의 Text를 여러 군데에서 생성해야 한다고 가정했을때,

커스텀 수식어를 하나 만들어 다른 Text에도 쉽고 빠르게 적용할 수 있습니다! 

 

 

먼저 CustomModifier 구조체를 만들고 ViewModifier protocol을 채택합니다.

body function을 구현해야 하는데, body function은 content를 받아 View 타입을 반환하도록 되어있습니다. 

 

이게 뭐냐!!

 

content 매개 변수는 수식해야 할 대상(뷰) 인데, 

body 메서드 내부에서 매개 변수로 들어온 content에 필요한 효과를 적용한 후에 반환하면 되는 겁니다! 간단하쥬? 

 

자, 한번 만들어봅시다! 

//[커스텀 수식어]
struct CustomModifier: ViewModifier {
    
    var fontSize: CGFloat
    
    func body(content: Content) -> some View {
        
        content
            .font(.system(size: fontSize))
            .foregroundColor(.blue)
        
    }
       
}

fontSize는 가변적으로 하기 위해 프로퍼티를 선언해서 font size에 적용시켰습니다!

그리고 색상은 파란색으로 설정했습니다.

 

이제 이 CustomModifier를 Text에 적용시키면 됩니다. 

커스텀 수식어는 .modifier() 수식어를 통해 적용합니다! 

//[ContentView]
struct ContentView: View {
    
    @State var fontSize: CGFloat = 30
    
    var body: some View {
        
        Text("Modifier")
            .italic()
            .modifier(CustomModifier(fontSize: fontSize))
    }
}

이렇게 적용하면?! 

아주 똑같이 잘 나오쥬? 

근데 뭔가 좀 이상합니다.

.foreground(), .bold() 이런 것처럼 수식어를 바로 적용하고 싶은데, 

.modifier() 안에다가 CustomModifier 구조체 인스턴스를 넣는게 어딘가 모르게 좀 어색해 보이죠? 

다른 수식어들 처럼 바로 적용할 수 있도록 해보겠습니다! 

extension View {
    func customText(fontSize: CGFloat) -> some View {
        self.modifier(
            CustomModifier(fontSize: fontSize)
        )
    }
}

View Extension에 수식어로 적용할 메서드를 하나 만들고, 

메서드 내부에서 modifier 수식어를 통해 CustomModifier를 적용시키고 반환합니다. 

 

이렇게하면?!  간단하게 적용시킬 수 있습니다 :) 

struct ContentView: View {
    
    @State var fontSize: CGFloat = 30
    
    var body: some View {
        VStack {
            
            HStack {
                Button(action: {self.fontSize += 1}) {
                    Image(systemName: "plus")
                }
                
                Button(action: {self.fontSize -= 1}) {
                    Image(systemName: "minus")
                }
            }
            .font(.title)
            
            
            Text("Modifier")
                .italic()
                .customText(fontSize: fontSize) //커스텀 수식어 적용
        }
    }
}

State프로퍼티래퍼로 만들어진 fontSize를 변경하면 변경된 fontSize가 CustomModifier에 반영됩니다!

 

 

오늘은 여기까지! 

궁금하신 사항 있으면 댓글 남겨주세요 :) 

댓글 없음:

댓글 쓰기