본 포스팅은 Swift 5.2.4 기준으로 작성되었습니다.
이번 포스팅에서는 Button 과 List (UIKit 의 UITableView 와 동일) 를 생성하는 방법을 공부해보도록 할게요. SwiftUI 에서는 Button 과 List 를 구현하는 코드도 단 몇 줄이면 충분합니다. 이게 다 오토레이아웃이 자동 적용되서 그런것 같아요.
Button
이전에 공부할 때 Text 가 View 라고했었으니까 Button 도 당연히 View 의 일종일거라 생각하고 따로 찾아보진 않으려고 했거든요? 근데 그래도 공식문서를 한번쯤 보는게 예의가 아닐까 싶어 찾아보니 View 가 아니였습니다. 안찾아봤으면 어쩔뻔!
Button 자체는 View 가 아니라 Control 이더라고요. 다만 Button 내의 Label 이 Generic 타입으로 구현되어 있고 이 Label 이 View 로 인식이 되는 형태입니다. 뭐 그래서 결국 Button 이 View 의 일종이 되는거긴 하지만 공식문서의 구분에서 control 로 구분하고 있어요.
버튼 생성은 Text 처럼 parenthesis(괄호) 안에 원하는 타이틀을 입력하고 brace(중괄호) 안에 버튼이 눌렸을 때 동작하기 원하는 코드를 작성하면 됩니다. 일단 우리는 버튼이 잘 동작하는지만 확인하면 되니까 버튼이 눌리면 “Button Pressed” 가 print 되는 코드를 구현해보록 하겠습니다.
var body: some View {
Button("Button") {
print("Button Pressed")
}
}
아래 결과를 보면 이번에도 코드 단 몇 줄만으로 Button 이 중앙에 잘 표시되고 있죠?
Preview 에서는 단순히 Button 의 위치를 확인하는 것 뿐 아니라 어떤 입력을 받을 때 특정 코드가 실행되는 것을 확인할 수 있습니다.
그렇다고 바로 누르면 되는건 아니고 Preview 를 기준으로 우측 하단에 위치한 두 개의 버튼 중 첫번째 버튼인 Live Preview 를 우클릭하면 좌측 이미지와 같은 창이 하나 뜨는데 이 중 두번째 메뉴인 Debug Preview 를 클릭해 봅시다.
잠시 로딩을 기다린 뒤 정상적으로 Debug Preview 가 활성화 된 상태에서 버튼을 눌러보면!! Button 액션으로 구현된 print 까지 console 에 printing 되는 것을 확인할 수 있습니다.
여기서 추가적으로 궁금증이 생겼는데 Preview 에서 Animation 까지 확인해 볼 수 있는 건지 궁금해졌어요. 이렇게 button action 까지 실행되는 것 보면 가능할 것 같기도 하고요 ㅎㅎㅎ 하지만 오늘은 기초적인 것들만 알아볼거니까 추가로 확인해보진 않을거에요 ㅎ
대신 버튼에 텍스트말고 이미지와 SF Symbol 을 넣을 수 있는 방법을 알아보도록 할게요.
HStack 을 사용해 Button 2개를 가로로 배치하고 첫번째 버튼에는 SwiftUI 이미지를, 두번째 버튼에는 SF Symbol “play.circle” 아이콘을 넣었어요.
주의해야할 점 하나가 있는데 SwiftUI 에서는 Button 이미지의 renderingMode 기본 값이 .template 으로 되어 있어 다운로드 받은 이미지의 경우 .original 로 변경을 해주어야 이미지가 정상적으로 보이게됩니다. SFSymbol 을 삽입한 경우에는 오히려 기본값이 .template 이라 별 다른 추가작업 없이도 색상이 변경가능하지만요!
var body: some View {
HStack(spacing: 20) {
Button(action: { print("Button 1") }) {
Image("SwiftUI")
.renderingMode(.original)
.resizable()
.frame(width: 120, height: 120)
}
Button(action: { print("Button 1") }) {
Image(systemName: "play.circle")
.imageScale(.large)
.font(.largeTitle)
}
.accentColor(.green)
}
}
위 코드를 입력하면 다음과 같은 결과를 확인해 볼 수 있습니다. 참고로 .accentColor 는 UIKit 의 tintColor 의 역할을 대신하며 색상을 바꿔주는 코드에요. 지금은 .green 을 적용해서 오른쪽 play.circle 이미지가 초록색으로 변했습니다.
List
List 가 뭘까요? UIKit 에서는 없던 이름이에요. UITableView 가 SwiftUI 에서 List 라는 이름으로 완전히 바뀌었습니다. 왜 굳이 Table 이 아니라 List 라고 했는지는 조금 의아하지만 아무튼 List 도 직관적이고 좋은 것 같아요 ㅎㅎ 근데 이러면 아직 SwiftUI 로는 지원되지 않는 UICollectionView 이름은 어떻게 정해질지 궁금해지네요.
위에서 Button 공식 문서를 봤더니 버튼 자체는 control 이지만 버튼 내부의 Label 이 View 타입이었던 것 기억하시죠? 이처럼 List 자체는 다른 타입이지만 내부의 어떤 것 때문에 View 로 인정되는 것 수 있을 것 같다는 의심이 들어 공식문서를 먼저 살펴보았습니다.
역시나!! List 는 View 가 아니라 data 를 row 의 형태로 나타낼 수 있는 container라고 하네요. 그럼 body 가 어떻게 View 로 받을 수 있느냐… 위 스크린샷에서 Generic 타입으로 SelectionValue 랑 Content 2가지가 있는걸 확인할 수 있는데요. 짤려서 보이지 않지만 이 중 content 가 View 타입입니다.
그럼 List 를 생성해볼게요.
var body: some View {
List{
Text("1")
}
}
네 이게 끝입니다. 정말로 List 가 생성이 되었다구요! UITableView 를 만들어보신 분들은 이게 얼마나 놀랍도록 간단한건지 느낄거에요!!
이전에 없던 옅은 선들이 보이시죠? 이게 바로 List 입니다. List 역시 Button 과 같은 방법으로 Preview 에서 스크롤을 실험해 볼 수 있습니다.
그런데 그냥 이렇게 빈 칸으로 두면 허전하니까 각 줄에 데이터를 몇가지 넣어보도록 할게요. List brace 안쪽으로 원하는 View 를 구현하면 각 instance 가 순서대로 List 의 row 에 추가되게 됩니다. 한번 확인해볼까요?
var body: some View {
List {
Text("List").font(.largeTitle)
Image("SwiftUI")
Circle().frame(width: 100, height: 100)
Color(.red).frame(width: 100, height: 100)
}
}
위 코드를 입력해보세요.
정말 그냥 적힌 순서대로 각 instance 가 List 의 row 에 추가됩니다. 다만 최대로 입력할 수 있는 instance 의 갯수는 10개라는거 기억하세요
당연히 데이터가 10개를 넘더라도 정상적으로 표시할 수 있는 방법이 있습니다.
var body: some View {
List(0..<100) {
Text("\($0)")
}
}
위 코드를 입력해보세요. 이런식으로 원하는 데이터를 마음껏 넣어줄 수 있습니다.
마지막으로 UITableView 하면 빼놓을 수 없는 것 중 Header 와 Footer 가 있었죠? 얘네를 List 에서 추가할 수 있는 방법을 알아보겠습니다.
List {
Section (
header: Text("Header1"),
footer: Text("Footer1")
) {
Text("1")
Text("2")
Text("3")
Text("SwiftUI")
}
Section (
header: Text("Header2"),
footer: HStack { Spacer(); Text("Footer2") }
) {
Text("Section2")
Text("SwiftUI")
}
}
.listStyle(GroupedListStyle())
}
List 내부에 Section 항목을 먼저 추가하고 header 와 footer 를 입력합니다. 그 다음 brace 를 열어 해당 Section 에 속하는 데이터들을 입력해주면 끝입니다. header 와 footer 는 기본적으로 좌정렬 되어 있으니까 우측에 표시하고 싶을 때는 HStack 을 사용해 Spacer 를 추가한 뒤 Text 를 입력해주면 됩니다.
추가적으로 .listStyle 이라는 코드가 보이죠? 얘는 GroupedListStyle 또는 DefualtListStyle 중에 선택할 수 있고, 결과에 따라 header 나 footer 가 List 가 스크롤 될 때 함께 스크롤 될지 아니면 남아있을지 설정할 수 있는 옵션입니다. 직접 한번 실험 해보시면 확실히 이해가 되실거에요.
이렇게 기본적인 List 의 생성 방법을 알아보았어요. UIKit 과 많이 달라진 방식이 아직은 서툴지만 또 쓰다보면 금방 익숙해질거에요. 그러니까 SwiftUI 도 미리미리 같이 공부해보자구요~~