반응형
LinkedIn 개발자로 성장하면서 남긴 발자취들을 확인하실 수 있습니다.
Github WWDC Student Challenge 및 Cherish, Tiramisul 등 개발한 앱들의 코드를 확인하실 수 있습니다.
개인 앱 : Cherish 내 마음을 들여다보는 시간, 체리시는 디자이너와 PM과 함께 진행 중인 1인 개발 프로젝트입니다.
10년 후, 20년 후 나는 어떤 스토리 텔러가 되어 있을지 궁금하다. 내가 만약에 아직 조금 더 탐구하고 싶은 게 있고, 궁금한 게 있다면, 그게 설사 지금 당장의 내 인생에 도움이 안 되는 것 같더라도 경험해보자. 그 경험들을 온전히 즐기며 내 것으로 만들고, 내 일에 녹여내고... 그러다보면 그 점들이 모여 나란 사람을 그려내는 선이 될 테니까.

Recent Posts
Recent Comments
Total
관리 메뉴

꿈꾸는리버리

SwiftUI : ViewModifier 본문

오뚝이 개발자/SwiftUI

SwiftUI : ViewModifier

rriver2 2022. 6. 1. 20:10
반응형

이번에는 modifier 코드를 줄이는 방법을 알아볼거다 !

요즘 NC1 이후 코드 정리를 하는데에 아쉬움이 남았던 부분들을 공부하는 중인데 하나 둘 포스팅을 하려 한다 !

 


 View를 다른 모습으로 modify 해주는 이 노란 칭구들이 modifier ! 

 

 이 버튼 3개를 만들기 위해서 사용한 modifier들을 줄여보자 ! 

 

여기 하단의 코드를 보면 

struct ViewModifierView: View {
    var body: some View {
        VStack{
            Text("button1")
                .font(.title3)
                .foregroundColor(.white)
                .padding()
                .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
                .background(
                    RoundedRectangle(cornerRadius: 8, style: .continuous)
                        .fill(.green)
                )
                .padding(.bottom, 8)
            
            Text("button2")
                .font(.title3)
                .foregroundColor(.white)
                .padding()
                .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
                .background(
                    RoundedRectangle(cornerRadius: 8, style: .continuous)
                        .fill(.black)
                )
                .padding(.bottom, 8)

            Text("button3")
                .font(.title3)
                .foregroundColor(.white)
                .padding()
                .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
                .background(
                    RoundedRectangle(cornerRadius: 8, style: .continuous)
                        .fill(.red)
                )
                .padding(.bottom, 8)
            
        }
    }
}

(######) 부분 빼고 반복을 하는 것을 확인할 수 있다..! 

                .font(.title3)
                .foregroundColor(######)
                .padding()
                .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
                .background(
                    RoundedRectangle(cornerRadius: 8, style: .continuous)
                        .fill(######)
                )
                .padding(.bottom, 8)

func으로 ... 빼고 싶지 않은가 !!

ㅎㅎ 이를 해결할 수 있는 방법을 소개하려 한다!

 


 1) extension View 이용 

View를 extension 해서 customButton이라는 함수를 선언하고, backgroundColor와 foregroundColor를 파라매터 값으로 받는다.

그리고 해당 변수들을 사용해 modify해서 View를 반환한다.

extension View {
    func customButton(backgroundColor : Color = .green, foregroundColor : Color = .white) -> some View{
        self
            .font(.title3)
            .foregroundColor(foregroundColor)
            .padding()
            .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
            .background(
                RoundedRectangle(cornerRadius: 8, style: .continuous)
                    .fill(backgroundColor)
                )
            .padding(.bottom, 8)
    }
}

struct ViewModifierView: View {
    var body: some View {
        VStack{
            Text("button1")
                .customButton(backgroundColor: .blue, foregroundColor: .white)
        }
    }
}

 


 2) ViewModifier 이용 

ViewModifier 프로토콜을 따르는 struct를 만들어서 modifier( modifier: )을 호출한다.

 

a)

struct ButtonModifier: ViewModifier{
    var backgroundColor : Color = .green
    var foregroundColor : Color = .white
    
    func body(content: Content) -> some View {
        content
            .font(.title3)
            .foregroundColor(foregroundColor)
            .padding()
            .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
            .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
                .fill(backgroundColor))
            .padding(.bottom, 8)
    }
}

struct ViewModifierView: View {
    var body: some View {
        VStack{
            Text("button3")
                .modifier(ButtonModifier(backgroundColor: .blue, foregroundColor: .white))
        }
    }
}

 

https://developer.apple.com/documentation/swiftui/viewmodifier

2번처럼 바로 View에 .modifier를 호출해도 되지만

1번처럼 View를 extension하는 방식이 보다 일반적이고 관용적인 접근이라고 한다.

 


그래서 하단처럼 작성하면 된다 !

b)

struct ButtonModifier: ViewModifier{
    var backgroundColor : Color
    var foregroundColor : Color
    
    func body(content: Content) -> some View {
        content
            .font(.title3)
            .foregroundColor(foregroundColor)
            .padding()
            .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
            .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
                .fill(backgroundColor))
            .padding(.bottom, 8)
    }
}

extension View {
    func customButton2(backgroundColor : Color = .green, foregroundColor : Color = .white) -> ModifiedContent<Self, ButtonModifier> {
        return modifier(ButtonModifier(backgroundColor : backgroundColor, foregroundColor : foregroundColor))
    }
}

struct ViewModifierView: View {
    var body: some View {
        VStack{
            Text("button1")
                .customButton2()
        }
    }
}

 


 +) 코드를 보면 눈치를 챘겠지만, 파라매터에 변수를 안 넣어도 된다! 

파라매터에 값이 안 들어왔을 때, backgroundColor는 .green으로, foregroundColor은 .white으로 들어간다.


 전체 코드 

import SwiftUI

struct ButtonModifier: ViewModifier{
    var backgroundColor : Color
    var foregroundColor : Color
    
    func body(content: Content) -> some View {
        content
            .font(.title3)
            .foregroundColor(foregroundColor)
            .padding()
            .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
            .background(RoundedRectangle(cornerRadius: 8, style: .continuous)
                .fill(backgroundColor))
            .padding(.bottom, 8)
    }
}

extension View {
    // 1번 방법
    func customButton(backgroundColor : Color = .green, foregroundColor : Color = .white) -> some View{
        self
            .font(.title3)
            .foregroundColor(foregroundColor)
            .padding()
            .frame(width: UIScreen.main.bounds.width-30, alignment: .center)
            .background(
                RoundedRectangle(cornerRadius: 8, style: .continuous)
                    .fill(backgroundColor)
                )
            .padding(.bottom, 8)
    }
    // 2번 방법
    func customButton2(backgroundColor : Color = .green, foregroundColor : Color = .white) -> ModifiedContent<Self, ButtonModifier> {
        return modifier(ButtonModifier(backgroundColor : backgroundColor, foregroundColor : foregroundColor))
    }
}


struct ViewModifierView: View {
    var body: some View {
        VStack{
            Text("button1")
                .customButton()
            
            Text("button2")
                .customButton2(backgroundColor: .orange, foregroundColor: .green)
        }
    }
}

 

 

출처 

: https://amehta.github.io/tips/custom-view-modifiers-in-swift-ui/

 

Custom View Modifiers in SwiftUI :: Tech Log — Hello Friend NG Theme

Last Run on XCODE 11.6 / Swift 5.2 In SwiftUI View(s) are the building blocks of the UI. All changes to the Views are done by calling special functions called modfiers that wrap up the original View with the needful changes and return a View back. In the e

amehta.github.io

https://developer.apple.com/documentation/swiftui/viewmodifier

 

Apple Developer Documentation

 

developer.apple.com

 

반응형
Comments