랜드마크 상세 뷰가 세팅되었으니, 랜드마크의 전체 리스트를 제공하는 방법을 제공해보자! 모든 랜드마크에 대한 정보를 표시할 수 있는 뷰를 만들고 사용자가 랜드마크에 대한 상세 뷰를 보기 위해 누를 수 있는 스크롤 목록을 동적으로 생성한 후, UI를 미세 조정하기 위해 Xcode의 canvas 를 사용하여 다양한 장치 크기에서 여러 preview 를 렌더링해보자.
첫 스텝으로, 모든 뷰의 정보의 하드코딩을 진행하자. 이때 뷰에 전달할 수 있는 데이터 저장 모델을 생성한다.
struct Landmark: Hashable, Codable {
var id: Int
var name: String
var park: String
var state: String
var description: String
private var imageName: String // 사용자가 관심 없는 부분은 private 처리
var image: Image {
Image(imageName)
}
private var coordinates: Coordinates
var locationCoordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: coordinates.latitude,
longitude: coordinates.longitude
)
}
struct Coordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
}
landmarkData.json
데이터 파일의 일부 키와 일치하는 프로퍼티로 타입 정의
var landmarks: [Landmark] = load("landmarkData.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \\(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \\(filename) from main bundle:\\n\\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \\(filename) as \\(T.self):\\n\\(error)")
}
}
파일의 랜드마크로 초기화 된 배열 생성
각 랜드마크에 대한 세부 정보를 보여주는 row 뷰를 만들어보자. row 뷰는 랜드마크에서 보여줘야 할 정보를 프로퍼티로 가지고 있기 때문에 어떤 랜드마크든 하나의 뷰로 표현할 수 있다. 이후 여러 row 뷰를 랜드마크 리스트로 결합시켜보자.
struct LandmarkRow: View {
var landmark: Landmark
var body: some View {
HStack {
landmark.image
.resizable()
.frame(width: 50, height: 50)
Text(landmark.name)
Spacer()
}
}
}