Skip to content

Commit

Permalink
Refactor: Section 2.1 update
Browse files Browse the repository at this point in the history
### Motivation
- Section 2.1. Create a Landmark Model

### Key Changes
- Section 2.1. Create a Landmark Model 예제 코드 및 주석 추가

### To Reviewers
- 없음
  • Loading branch information
garlicvread committed Aug 11, 2022
1 parent e3dcb5a commit a53bd24
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 79 deletions.
194 changes: 194 additions & 0 deletions Resource/landmarkData.json

Large diffs are not rendered by default.

36 changes: 32 additions & 4 deletions tutorial.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
941CE6BB28A4963700484938 /* CircleImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941CE6B928A4963700484938 /* CircleImage.swift */; };
941CE6C028A496ED00484938 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 941CE6BF28A496ED00484938 /* Assets.xcassets */; };
941CE6C228A499BD00484938 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941CE6C128A499BD00484938 /* MapView.swift */; };
941CE6C428A4B39000484938 /* landmarkData.json in Resources */ = {isa = PBXBuildFile; fileRef = 941CE6C328A4B39000484938 /* landmarkData.json */; };
941CE6C628A4B42100484938 /* Landmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941CE6C528A4B42100484938 /* Landmark.swift */; };
941CE6C828A4B83C00484938 /* ModelData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941CE6C728A4B83C00484938 /* ModelData.swift */; };
9D5E3EBA280475CB0076AFDF /* tutorialApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5E3EB9280475CB0076AFDF /* tutorialApp.swift */; };
9D5E3EBC280475CB0076AFDF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5E3EBB280475CB0076AFDF /* ContentView.swift */; };
9D5E3EC1280475CC0076AFDF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D5E3EC0280475CC0076AFDF /* Preview Assets.xcassets */; };
Expand All @@ -21,6 +24,9 @@
941CE6B928A4963700484938 /* CircleImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircleImage.swift; sourceTree = "<group>"; };
941CE6BF28A496ED00484938 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../tutorial/Assets.xcassets; sourceTree = "<group>"; };
941CE6C128A499BD00484938 /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = "<group>"; };
941CE6C328A4B39000484938 /* landmarkData.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = landmarkData.json; sourceTree = "<group>"; };
941CE6C528A4B42100484938 /* Landmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Landmark.swift; sourceTree = "<group>"; };
941CE6C728A4B83C00484938 /* ModelData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelData.swift; sourceTree = "<group>"; };
9D5E3EB6280475CB0076AFDF /* SwiftUITutorialWithNotes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUITutorialWithNotes.app; sourceTree = BUILT_PRODUCTS_DIR; };
9D5E3EB9280475CB0076AFDF /* tutorialApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = tutorialApp.swift; sourceTree = "<group>"; };
9D5E3EBB280475CB0076AFDF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand All @@ -42,10 +48,31 @@
isa = PBXGroup;
children = (
941CE6BF28A496ED00484938 /* Assets.xcassets */,
941CE6C328A4B39000484938 /* landmarkData.json */,
);
path = Resource;
sourceTree = SOURCE_ROOT;
};
941CE6C928A4BA0E00484938 /* Views */ = {
isa = PBXGroup;
children = (
9D5E3EBB280475CB0076AFDF /* ContentView.swift */,
940ECDAD28A37ECF00092638 /* MainContentView.swift */,
941CE6B928A4963700484938 /* CircleImage.swift */,
941CE6C128A499BD00484938 /* MapView.swift */,
);
path = Views;
sourceTree = "<group>";
};
941CE6CA28A4BA1500484938 /* Model */ = {
isa = PBXGroup;
children = (
941CE6C528A4B42100484938 /* Landmark.swift */,
941CE6C728A4B83C00484938 /* ModelData.swift */,
);
path = Model;
sourceTree = "<group>";
};
9D5E3EAD280475CB0076AFDF = {
isa = PBXGroup;
children = (
Expand All @@ -65,12 +92,10 @@
9D5E3EB8280475CB0076AFDF /* tutorial */ = {
isa = PBXGroup;
children = (
941CE6C928A4BA0E00484938 /* Views */,
941CE6CA28A4BA1500484938 /* Model */,
941CE6BC28A496B500484938 /* Resource */,
9D5E3EB9280475CB0076AFDF /* tutorialApp.swift */,
9D5E3EBB280475CB0076AFDF /* ContentView.swift */,
940ECDAD28A37ECF00092638 /* MainContentView.swift */,
941CE6B928A4963700484938 /* CircleImage.swift */,
941CE6C128A499BD00484938 /* MapView.swift */,
9D5E3EBF280475CC0076AFDF /* Preview Content */,
);
path = tutorial;
Expand Down Expand Up @@ -144,6 +169,7 @@
files = (
9D5E3EC1280475CC0076AFDF /* Preview Assets.xcassets in Resources */,
941CE6C028A496ED00484938 /* Assets.xcassets in Resources */,
941CE6C428A4B39000484938 /* landmarkData.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -159,6 +185,8 @@
941CE6C228A499BD00484938 /* MapView.swift in Sources */,
9D5E3EBA280475CB0076AFDF /* tutorialApp.swift in Sources */,
940ECDAE28A37ECF00092638 /* MainContentView.swift in Sources */,
941CE6C628A4B42100484938 /* Landmark.swift in Sources */,
941CE6C828A4B83C00484938 /* ModelData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Binary file not shown.
66 changes: 0 additions & 66 deletions tutorial/MainContentView.swift

This file was deleted.

49 changes: 49 additions & 0 deletions tutorial/Model/Landmark.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Landmark.swift
// tutorial
//
// Created by 김제필 on 8/11/22.
//

import Foundation
import SwiftUI // 2.1.5. imageName 변수 추가를 위한 프레임워크 호출
import CoreLocation // 2.1.7. computed property인 locationCoordinates를 위한 라이브러리

// 2.1.3. Landmark 구조체(structure) 정의
// 몇 가지 필요한 데이터가 이미 landmarkData.json 파일에 담겨 있는데, 이 json파일에 담겨 있는 데이터의 항목명과 동일하게 항목을 작성한다.
// Codable 옵션은 데이터를 Landmark 구조체와 json 파일 간 데이터 전송을 위한 것
// 나중에 Codable 프로토콜의 Decodable 컴포넌트가 사용됨: 파일에서 데이터를 읽기 위한 것.
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String

// 2.1.5. imageName 변수 추가: Assets에 등록된 이미지 파일의 파일명을 읽어오기 위한 것
private var imageName: String
var image: Image {
Image(imageName)
}

// 2.1.6. 랜드마크 위치 정보를 담기 위한 변수 coordinates 선언
private var coordinates: Coordinates

// 2.1.7. locationCoordinate: computed property -> var 로 선언
// computed property는 다른 속성을 기반으로 해당 속성 값이 결정됨. 즉, 메모리 공간을 가지지 않음.
// 선언 시점에 기본값을 저장하지 않으므로 형식 추론이 불가능하며, 따라서 반드시 자료형(Type)을 같이 선언해야 함
var locationCoordinates: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: coordinates.latitude,
longitude: coordinates.longitude)
}


struct Coordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
}


// 여기까지 코딩이 됐으면 이제 ModelData.swift 파일을 작성해야 한다.
// ModelData.swift 파일을 생성하자. 일반 Swift 파일이다.
40 changes: 40 additions & 0 deletions tutorial/Model/ModelData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// ModelData.swift
// tutorial
//
// Created by 김제필 on 8/11/22.
//

import Foundation

// 2.1.10 landmarkData.json의 데이터를 받아올 어레이 선언
var landmarks: [Landmark] = load("landmarkData.json")

// 2.1.9. 애플리케이션의 메인 번들에서 지정된 이름의 json 데이터를 가져오는 메서드 생성
// load 메서드는 Codable 프로토콜의 구성요소인 Decodable 프로토콜의 반환 타입을 따른다.
func load<T: Decodable>(_ filename: String) -> T {
let data: Data

guard let file = Bundle.main.url(forResource: filename,
withExtension: nil)
else {
fatalError("Canot find \(filename) in main bundle.")
}

do {
data = try Data(contentsOf: file)
} catch {
fatalError("Cannot load \(filename) from main bundle:\n\(error)")
}

do {
let decoder = JSONDecoder()

return try decoder.decode(T.self, from: data)
} catch {
fatalError("Cannot parse \(filename) as \(T.self):\n\(error)")
}
}

// 여기까지 작업이 끝났다면 디렉토리를 정리하자.
// 어떤 디렉토리에 어떤 파일을 배치할 것인지는 공식 문서를 보면 나옴.
10 changes: 5 additions & 5 deletions tutorial/CircleImage.swift → tutorial/Views/CircleImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import SwiftUI

struct CircleImage: View {
var body: some View {
Image("turtlerock") // 4.3. TextView -> Image initializer로 변경
.clipShape(Circle()) // 4.4. 이미지 원형으로 잘라내기(마스크 추가)
.overlay { // 4.5. 회색 테두리 원 생성 후 overlay에 추가
Circle().stroke(.white, lineWidth: 4) // 4.7. 테두리 흰색으로 변경
Image("turtlerock") // 1.4.3. TextView -> Image initializer로 변경
.clipShape(Circle()) // 1.4.4. 이미지 원형으로 잘라내기(마스크 추가)
.overlay { // 1.4.5. 회색 테두리 원 생성 후 overlay에 추가
Circle().stroke(.white, lineWidth: 4) // 1.4.7. 테두리 흰색으로 변경
}
.shadow(radius: 7) // 4.6. 그림자 효과 추가
.shadow(radius: 7) // 1.4.6. 그림자 효과 추가
}
}

Expand Down
File renamed without changes.
66 changes: 66 additions & 0 deletions tutorial/Views/MainContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// MainContentView.swift
// tutorial
//
// Created by 김제필 on 8/10/22.
//

import Foundation
import SwiftUI

// View 프로토콜 렌더링을 위한 구조체(Structure)
struct MainContentView: View {
var body: some View {
// 1.6.2. 기존 VSTack을 감쌀 새 VStack 삽입
VStack {
// 1.6.3. MapView 가져오기, 6.4. 리이브 프리뷰로 확인
MapView()
.ignoresSafeArea(edges: .top) // 1.6.8. safe area 무시 옵션 추가
.frame(height: 300)

CircleImage() // 1.6.5. CircleImage 뷰 추가
.offset(y: -130) // 1.6.6. y축 offset 값 -130으로 설정 -> MapView 위에 CircleImage를 겹쳐 표시
.padding(.bottom, -130) // 1.6.6. 하단 padding값도 -130으로 설정 -> 아래 텍스트 뷰와의 거리 조절

// 1.3.1., 1.3.2. VStack 추가
VStack(alignment: .leading) { // 1.3.5. alignment 옵션 추가
Text("Turtle Rock")
.font(.title)

// 1.3.6. HSTack 추가
HStack {
Text("Joshua Tree National Park") // 1.3.3. TextView의 placeholder 변경
// .font(.subheadline) // 1.3.4. 폰트 변경

Spacer() // 1.3.8. Spacer 추가

Text("California") // 1.3.7. TextView 추가
// .font(.subheadline)
}
.font(.subheadline) // 1.6.10. 폰트 설정 이동
.foregroundColor(.secondary) // 1.6.10. 폰트 색상 변경

Divider() // 1.6.9. divider 및 기타 정보를 표시하는 Text 추가

Text("About Turtle Rock")
.font(.title2)

Text("Descriptive text goes here.")
}
.padding() // 1.3.9. 패딩 추가

Spacer() // 1.6.7. Spacer 추가 -> 전체 오브젝트를 화면 상단으로 배치
}

}
}


struct MainContentView_Previews: PreviewProvider {
static var previews: some View {
MainContentView()
}
}

// 이제 CircleImage.swift 파일을 작성한다.
// CircleImage.swift 파일은 SwiftUIView를 위한 파일이다.
8 changes: 4 additions & 4 deletions tutorial/MapView.swift → tutorial/Views/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
//

import SwiftUI
import MapKit // 5.2. MapKit 프레임워크 가져오기
import MapKit // 1.5.2. MapKit 프레임워크 가져오기

struct MapView: View {

// 5.3. 위치 정보를 담는 변수 region에 @State 옵션 추가
// 1.5.3. 위치 정보를 담는 변수 region에 @State 옵션 추가
// @State 옵션(attribute)를 추가하는 경우 그 변수의 데이터가 변동되면 자동으로 뷰가 업데이트된다.
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 34.011_286,
Expand All @@ -20,13 +20,13 @@ struct MapView: View {
)

var body: some View {
Map(coordinateRegion: $region) // 5.4. MapView 추가
Map(coordinateRegion: $region) // 1.5.4. MapView 추가
// @State private var region 값을 받아옴.
}
}


// 5.5. Previews 가 static 선언돼 있는 경우 native SwiftUI view만을 렌더링한다.
// 1.5.5. Previews 가 static 선언돼 있는 경우 native SwiftUI view만을 렌더링한다.
// MapView를 보려면 라이브 프리뷰 버튼을 눌러야 함.
struct MapView_Previews: PreviewProvider {
static var previews: some View {
Expand Down

0 comments on commit a53bd24

Please sign in to comment.