SwiftUI로 커스텀 뷰 생성하기

강기환·2022년 11월 9일
post-thumbnail

1. 기본 뷰 생성하기

File -> New -> File... 메뉴를 선택하고 템플릿 화면에서 SwiftUI View파일 항목을 선태갛여 프로젝트에 추가할 수 있다.
디폴트 SwiftUIView 파일은 ContentView.swift라는 이름으로 만들어진다.

2. 뷰 추가하기

body 프로퍼티에 원하는 뷰를 배치하여 다른 뷰가 추가될 수 있다. body프로퍼티는 단 하나의 뷰를 반환하도록 구성되어 있으므로 뷰를 추가하기 위해서는 스택이나 폼같은 컨테이너 뷰에 뷰들을 배치해야 한다.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
			Text("Goodbye World!")
        }
    }
}

앞의 예제는 수직 스택에 두 개의 Text 뷰가 배치되었는데 '수직스택'은 안에 포함되는 뷰들이 수직 방향으로 배치된다.
SwiftUI 뷰는 기본적으로 부모 뷰와 자식 뷰 형태의 계층구조가 된다. 이것은 여러 계층의 뷰들이 복잡한 사용자 인터페이스를 생성할 수 있게 한다.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
			Text("Goodbye World!")
            HStack{
            	Text("Text1")
                Text("Text2")
            }
        }
    }
}

컨테이너에 포함된 여러 뷰를 서로 연결하면 하나의 뷰처럼 간주된다.

struct ContentView: View {
	var body: some View {
    	Text("Hello ") + Text("how ") + Text("are you?")
    }
}

3. 하위 뷰로 작업하기

애플은 최대한 뷰를 작고 가볍게 하라고 권장한다. 이것은 재사용할 수 있는 컴포넌트 생성을 권장하고, 뷰 선언부를 더 쉽게 관리하도록 하며, 레이아웃이 더 효율적으로 렌더링되도록 권장한다.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
			Text("Goodbye World!")
			MyHStackView()
        }
    }
}

struct MyHStackView: View {
	var body: some View {
    	HStack {
        	Text("Text 1")
            Text("Text 2")
        }
    }
}

4. 프로퍼티로서의 뷰

하위 뷰를 생성하는 것 외에도 복잡한 뷰 계층구조를 구성하는 방법으로 프로퍼티를 뷰에 할당할 수도 있을 것이다.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Main Title")
            	.font(.largeTitle)
            HStack {
            	Text("Car Image")
                Image(systemName: "car.fill")
            }
        }
    }
}
struct ContentView: View {
	let carStack = HStack {
    	Text("Car Image")
        Image(systemName: "car.fill")
    }
    
    var body: some View {
        VStack {
            Text("Main Title")
            	.font(.largeTitle)
			carStack
        }
    }
}

5. 뷰 변경하기

모든 SwiftUI 뷰에는 뷰의 모양과 동작을 변경하는 데 사용될 수 있는 수정자들이 있다.
수정자는 커스텀 하위 뷰에도 적용할 수 있다.

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Main Title")
            MyHStackView()
            	.font(.largeTitle)
        }
    }
}

6. 텍스트 스타일로 작업하기

텍스트 스타일을 이용하여 뷰의 폰트를 선언했다면 텍스트 크기는 사용자가 지정한 폰트 크기에 따라 동적으로 맞춰진다. 다음의 텍스트 스타일은 현재 사용할 수 있는 옵션들이다.
1. headline
2. subheadline
3. body
4. callout
5. footnote
6. caption
폰트 종류와 크기를 선언하여 커스텀 폰트를 적용할 수도 있다. 이렇게 하면 사용자가 선택한 텍스트 크기와는 상관없이 고정된 크기로 표시될 것이다.

Text("Sample Text")
	.font(.custom("Copperplate", sixe: 70))

7. 수정자 순서

수정자들을 연결할 때 수정자들이 적용되는 순서가 중요하다.

Text("Sample Text")
	.border(Color.black)
    .padding()

border 수정자는 뷰 주변에 검정색 경계선을 그리며, padding 수정자는 뷰 주변의 여백을 추가한다.

Text("Sample Text")
    .padding()
	.border(Color.black)

8. 커스텀 수정자

SwiftUI는 커스텀 수정자를 생성할 수 있게 해준다. 이것은 뷰에 자주 적용되는 대표적인 수정자들을 갖고자 할 때 특히 유용하다.

Text("Text 1")
	.font(.largeTitle)
    .background(Color.white)
    .border(Color.gray, width: 0.2)
    .shadow(color: Color.black, radius: 5, x: 0, y: 5)
struct StandardTitle: ViewModifier {
	func body(content: Content) -> some View {
    	content
			.font(.largeTitle)
    		.background(Color.white)
    		.border(Color.gray, width: 0.2)
    		.shadow(color: Color.black, radius: 5, x: 0, y: 5)
    }
}
Text("Text 1")
	.modifier(StandardTitle())

9. 기본적인 이벤트 처리

Button 뷰는 버튼 내용과 함께 클릭이 감지될때 호출될 메서드로 선언되어야 한다.
다음의 구현체는 Text 뷰를 감싸는 Button 뷰로, 클릭하면 buttonPressed()라는 메서드가 호출된다.

struct ContentView: View {
	var body: some View {
    	Button(action: buttonPressed) {
        	Text("Click Me")
        }
    }
    
    func buttonPressed() {
    	
    }

액션 함수를 지정하는 대신, 버튼이 클릭되었을 때 실행될 코드를 클로저로 지정할 수 있다.

Button(action: {

}) {
	Text("Click Me")
}

Image 뷰를 버튼으로 만들어야 하는 경우도 있다.

Button(action: {
	print("hello")
}) {
	Image(systemName: "square.and.arrow.down")
}

10. onAppear, onDisappear 메서드

레이아웃 안에 뷰가 나타나거나 사라질 때 초기화 작업과 초기화 해제 작업을 수행하기 위하여 지정된 뷰에 액션 메서드들을 선언하기도 한다.

Text("Hello World")
	.onAppear(perform: {
    	// 뷰가 나타날 때 수행되는 토드
    })
    .onDisappear(perform: {
    	// 뷰가 사라질 때 수행되는 코드
    })

11. 커스텀 컨테이너 뷰 만들기

3개의 텍스트 뷰가 VStack 안에 포함되고 임의의 간격과 폰트 설정으로 구성된 하위 뷰가 다음과 같이 있다고 하자.

struct MyVStack: View {
	var body: some View {
    	VStack(spacing: 10) {
        	Text("Text Item 1")
            Text("Text Item 2")
            Text("Text Item 3")
        }
        .font(.largeTitle)
    }
}

간격이 10이며 largeTitle 폰트 수정자를 가진 VStack이 프로젝트 내에서 자주 필요하지만, 사용할 곳마다 서로 다른 뷰들이 여기에 담겨야 한다고 가정하자. 하위뷰를 사용해서는 이러한 유연성을 갖기 못하지만, 커스텀 컨테이너 뷰를 생성할 때 SwiftUI의 ViewBuilder 클로저 속성을 이용하면 가능하다.

ViewBuilder는 스위프트 클로저 형태를 취하며 여러 하위 뷰로 구성된 커스텀 뷰를 만드는데 사용될 수 있으며, 이 뷰가 레이아웃 선언부 내에 사용될 때까지 내용을 선언할 필요가 없다. ViewBuilder 클로저는 콘텐트 뷰들을 받아서 동적으로 만들어진 단일 뷰로 반환한다.

struct MyVStack<Content: View>: View {
	let content: () -> Content
    init(@ViewBuilder content: @escaping () -> Content) {
    	self.content = content
    }
    
    var body: some View {
    	VStack(spacing: 10) {
        	content()
        }
        .font(.largeTitle)
    }
}
MyVStack {
	Text("Text 1")
    Text("Text 2")
    HStack {
    	Image(systemName: "star.fill")
        Image(systemName: "star.fill")
    }
}
profile
백엔드개발자 꿈나무

0개의 댓글