프로젝트 생성 시 Interface에서 SwiftUI를 선택한다.
ContentView 라는 Struct가 자동 생성되어있다.
오른쪽 preview화면에서 resume버튼을 누르면 Hello, world! 텍스트가 잘보인다.
이제 body에 아래 코드를 넣어보자.
var body: some View {
NavigationView {
List {
Text("Hello World")
Text("Hello World")
Text("Hello World")
}
.navigationTitle("Menu")
}
}
https://www.hackingwithswift.com/samples/idine.zip 에서 받은 menu.json 파일을 프로젝트에 추가하고 메뉴들과 테이블 섹션의 정보를 담을 MenuSection과 MenuItem을 추가했다.
extension Bundle {
func decode<T: Decodable>(_ type: T.Type, from file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
let menu = Bundle.main.decode([MenuSection].self, from: "menu.json")
section별로 아이템들을 보여주기위해 List 안쪽을 수정했다.
var body: some View {
NavigationView {
List {
ForEach(menu) { section in
Text(section.name)
ForEach(section.items) { item in
Text(item.name)
}
}
}
.navigationTitle("Menu")
}
}
ForEach Block을 이용해서 menu에 있는 section 과 item들을 Text로 보여준다.
이제 Section을 Section답게 수정해보자.
List안쪽에 Text대신 Section을 만들고 그 안에 아이템들을 보여주는 ForEach문을 넣어준다.
NavigationView 에 GroupedListStyle() 을 적용해 좀더 이쁘게 구성해 본다.
var body: some View {
NavigationView {
List {
ForEach(menu) { section in
Section(header: Text(section.name)) {
ForEach(section.items) { item in
Text(item.name)
}
}
}
}
.navigationTitle("Menu")
}.listStyle(GroupedListStyle())
}
이제 메뉴아이템 row를 업그레이드해보자.
ItemRow struct를 하나 만들고 View프로토콜을 따르게한다.
MenuItem에 preview 확인용도로 사용할 example을 만들어둔다.
struct ItemRow : View {
let item: MenuItem
var body: some View {
Text(item.name)
}
}
struct ItemRow_Previews: PreviewProvider {
static var previews: some View {
ItemRow(item: MenuItem.example)
}
}
body에서 두가지 View가 리턴되는 경우 어떻게 처리될까?
var body: some View {
Image(item.thumbnailImage)
Text(item.name)
}
위 처럼 Image와 Text가 있는 경우 SwiftUI는 첫번째 View만을 보여준다.(여기서는 Image만을 보여준다.)
View를 정렬해서 보여주고 싶다면 HStack 이나 VStack을 사용하면된다.
body안쪽을 아래처럼 수정해본다.
var body: some View {
HStack {
Image(item.thumbnailImage)
.clipShape(Circle())
.overlay(Circle().stroke(Color.gray, lineWidth: 2))
VStack(alignment: .leading) {
Text(item.name)
.font(.headline)
Text("$\(item.price)")
}
}
}
var body: some View {
NavigationView {
List {
ForEach(menu) { section in
Section(header: Text(section.name)) {
ForEach(section.items) { item in
ItemRow(item: item)
}
}
}
}
.navigationTitle("Menu")
}.listStyle(GroupedListStyle())
}