https://gist.github.com/twostraws/aa18008c3dd3997e133aa92bde2ad8c7 이 페이지의 url을 이용해서 wikipedia의 정보를 불러와 선택한 장소 근처의 결과를 화면에 나타냈다.
먼저, JSON 코드의 틀인 Result를 생성한다.
struct Result: Codable {
let query: Query
}
struct Query: Codable {
let pages: [Int: Page]
}
struct Page: Codable {
let pageid: Int
let title: String
let terms: [String: [String]]?
}
그리고 정보를 받아오면 화면에 나타낼 형태로 View를 설정한다. load 중인지, 완료했는지, 실패했는지에 따라 화면을 달리 나타내야 하기에 enum으로 설정했다.
enum LoadingState {
case loading, loaded, failed
}
// ...
@State private var loadingState = LoadingState.loading
@State private var pages = [Page]()
Section("Nearby") {
switch loadingState {
case .loading:
Text("Loading...")
case .loaded:
ForEach(pages, id: \.pageid) { page in
Text(page.title)
.font(.headline)
+ Text(": ") +
Text("Page description here")
.italic()
}
case .failed:
Text("Please, try again.")
}
}
마지막으로 wikipedia에서 정보를 불러오는 함수 fetchNearbyPlaces()
를 설정하고 .task로 실행하면 된다.
func fetchNearbyPlaces() async {
let urlString = "https://en.wikipedia.org/w/api.php?ggscoord=\(location.latitude)%7C\(location.longitude)&action=query&prop=coordinates%7Cpageimages%7Cpageterms&colimit=50&piprop=thumbnail&pithumbsize=500&pilimit=50&wbptterms=description&generator=geosearch&ggsradius=10000&ggslimit=50&format=json"
guard let url = URL(string: urlString) else {
print("Wrong url: \(urlString)")
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
let decoded = try JSONDecoder().decode(Result.self, from: data)
pages = decoded.query.pages.values.sorted { $0.title < $1.title }
loadingState = .loaded
} catch {
loadingState = .failed
}
}
예시 말고도 다른 지역에서 잘 작동하는 것을 확인할 수 있다.
Page
가 여러 곳일 때 알파벳 순으로 정렬되도록 연산자 overloading을 설정했다.
static func <(lhs: Page, rhs: Page) -> Bool {
lhs.title < rhs.title
}
관련 장소에 설명이 있다면 title
옆에 보이도록 설정했다.
var description: String {
terms?["description"]?.first ?? "No further information"
}
평양 위치에 찍어서 확인해보면 이렇게 알파벳 순으로 관련 장소가 정렬되고, 장소의 설명이 italic체로 보인다.