iOS

[SwiftUI] View Modifier - customize your object!

녕이 2022. 9. 29. 10:25
728x90

 

 

📌 Overviews

이미 SwiftUI에는 font(), background(), shadow() 등 여러 build-in modifier가 존재한다. 이 modifier를 붙여서 재미있게 UI를 구성할 수 있다. 그런데 어 이런 modifier가 없다고?? 혹은 아 이런 건 있으면 좋을 거 같은데, 혹은 간격이랑 색상을 통일하면 좋을 텐데 이걸 다 언제 매번 붙이지 와 같은 생각이 들 때가 있다. 이럴 땐, 직접 modifier를 커스텀하면 된다. 커스텀을 하게 되면 다른 화면에서도 이 요소들을 간편하게 적용할 수 있다. 사실 이론적으로, 다른 사람의 코드는 자주 봐왔기 때문에 어느정도 알긴 하지만 직접 커스텀해본 적은 없기 때문에 낯설다. 좀 더 편하게 사용하고, 능숙해지기 위해 다양한 예제를 직접 만들어보자!

 

 

📌How to create a custom modifier?

custom modifier를 만들기 위해선, ViewModifier 프로토콜을 준수하는 새로운 struct을 만들어야 한다. 그리고 이 struct 안에는 some View를 반환하는 body 메서드를 정의해줘야 한다. 즉, 새로운 View를 만들어주는 것이다.

 

예를 들어, 앱 내의 모든 title이 특정한 스타일을 가지길 원한다고 가정해보자. 아래 코드와 같이 커스텀 ViewModifier를 만들어줘야 한다.

 

import SwiftUI

struct Title: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.callout)
            .foregroundColor(.white)
            .padding()
            .background(Color.accentColor)
            .clipShape(RoundedRectangle(cornerRadius: 12))
    }
}

//이렇게 생성한 modifier를 사용하려면 modifier()라는 modifier를 사용해야 한다.
struct CustomModifierStudy: View {
    var body: some View {
        Text("Hello, World!")
            .modifier(Title())
    }
}

 

modifier() view modifier를 사용하지 않고 extension을 사용하면 더 편리하다.

 

struct CustomModifierStudy: View {
    var body: some View {
        Text("Hello, World!")
            .titleStyle()
    }
}

extension View {
    func titleStyle() -> some View {
        modifier(Title())
    }
}

 

 

짜잔! 드디어 내 생애 첫번째 custom view modifier를 만들어냈다. 훨씬 깔끔하고, 보기도 좋고, 무엇보다 수정이 편리해졌습니다. ViewModifier 구조체 내 코드만 수정하면 되니까!

 

 

Custom ViewModifier는 이미 존재하는 다른 modifier를 더 적용할 수 있다. 이 또한 새로운 View 구조체를 생성해야 한다.

→ modifier는 기존 modifier를 수정하는 대신 새로운 modifier를 반환한다.

 

import SwiftUI

struct WaterMark: ViewModifier {
    var text: String
    
    func body(content: Content) -> some View {
        ZStack(alignment: .bottomTrailing) {
            content
            Text(text)
                .font(.caption)
                .foregroundColor(.white)
                .padding(5)
                .background(Color.black)
        }
    }
}

struct CustomModifierStudy: View {
    @State private var description : String = "scrap"
    var body: some View {
        Image("scrap")
            .resizable()
            .frame(width: 200, height: 200)
            .waterMarked(with: description)
    }
}

extension View {
    func waterMarked(with text: String) -> some View {
        modifier(WaterMark(text: text))
    }
}

 

 

content는 modifier가 적용되는 대상 객체고, 이에 맞춰서 ZStack으로 content 위에 Text를 올려줬다.

 

 

 

728x90