SwiftUI學(xué)習(xí)100天(Day71 - 項(xiàng)目 14,第四部分)

原創(chuàng)鏈接:https://www.hackingwithswift.com/100/swiftui
以下內(nèi)容僅供學(xué)習(xí)參考:

達(dá)到這一點(diǎn)需要一段時(shí)間,但今天你將使用非常少的代碼來(lái)實(shí)現(xiàn)一些應(yīng)用程序功能 - 這應(yīng)該是相對(duì)容易的一天!
更具體地說(shuō),你將了解如何根據(jù)枚舉的值顯示不同的 UI,如何為我們從網(wǎng)絡(luò)請(qǐng)求中獲取的某些數(shù)據(jù)添加自定義Comparable
一致性,等等。這里有一些重要的技術(shù),但它們確實(shí)讓我們的應(yīng)用程序更上一層樓。
如果你覺(jué)得這很難,那么你最好記住 William Eardley 曾經(jīng)說(shuō)過(guò)的話:“雄心壯志是通往成功的道路,堅(jiān)持是你到達(dá)的工具。”?你在開(kāi)始這門(mén)課程時(shí)表現(xiàn)出了雄心壯志,現(xiàn)在你已經(jīng)到了第 71 天,你顯然也表現(xiàn)出了毅力!
今天你有兩個(gè)主題需要完成,其中你將進(jìn)行網(wǎng)絡(luò)調(diào)用、添加Comparable
一致性等等。

從維基百科下載數(shù)據(jù)
為了使整個(gè)應(yīng)用程序更有用,我們將修改EditView
屏幕以顯示有趣的地方。畢竟,如果游覽倫敦在你的旅行清單上,你可能需要一些關(guān)于附近景點(diǎn)的建議。這聽(tīng)起來(lái)很難,但實(shí)際上我們可以使用 GPS 坐標(biāo)查詢維基百科,它會(huì)發(fā)回附近地點(diǎn)的列表。
維基百科的 API 以精確的格式發(fā)回 JSON 數(shù)據(jù),因此我們需要做一些工作來(lái)定義Codable
能夠存儲(chǔ)所有數(shù)據(jù)的結(jié)構(gòu)。結(jié)構(gòu)是這樣的:
主要結(jié)果將我們的查詢結(jié)果包含在一個(gè)名為“query”的鍵中。
查詢內(nèi)部是一個(gè)“頁(yè)面”字典,頁(yè)面 ID 作為鍵,維基百科頁(yè)面本身作為值。
每個(gè)頁(yè)面都有很多信息,包括它的坐標(biāo)、標(biāo)題、術(shù)語(yǔ)等等。
我們可以使用三個(gè)鏈接的結(jié)構(gòu)來(lái)表示,因此創(chuàng)建一個(gè)名為 Result.swift 的新 Swift 文件并為其提供以下內(nèi)容:
我們將使用它來(lái)存儲(chǔ)我們從維基百科獲取的數(shù)據(jù),然后立即在我們的 UI 中顯示它。然而,我們需要在抓取發(fā)生時(shí)顯示一些東西——一個(gè)顯示“正在加載”或類(lèi)似內(nèi)容的文本視圖應(yīng)該可以解決問(wèn)題。
這意味著根據(jù)當(dāng)前加載狀態(tài)有條件地顯示不同的 UI,這意味著定義一個(gè)實(shí)際存儲(chǔ)當(dāng)前加載狀態(tài)的枚舉,否則我們不知道要顯示什么。
首先將此嵌套枚舉添加到EditView
:
這些涵蓋了我們代表網(wǎng)絡(luò)請(qǐng)求所需的所有狀態(tài)。
接下來(lái),我們將向 EditView
中添加兩個(gè)屬性
:一個(gè)表示加載狀態(tài),一個(gè)用于在獲取完成后存儲(chǔ)一組維基百科頁(yè)面。所以,現(xiàn)在添加這兩個(gè):
在我們處理網(wǎng)絡(luò)請(qǐng)求本身之前,我們還有最后一項(xiàng)簡(jiǎn)單的工作要做:添加到我們Form
的新部分以顯示頁(yè)面(如果已加載)或狀態(tài)文本視圖。我們可以將這些if/else if
條件或switch
語(yǔ)句直接放入Section
,SwiftUI 會(huì)計(jì)算出來(lái)。
因此,將此部分放在現(xiàn)有部分下方:
提示:請(qǐng)注意我們?nèi)绾问褂?span id="s0sssss00s" class="color-pink-02">+
將文本視圖一起添加?這讓我們可以創(chuàng)建更大的文本視圖來(lái)混合和匹配不同類(lèi)型的格式?!按颂幍捻?yè)面描述”只是暫時(shí)的——我們很快就會(huì)更換它。
現(xiàn)在是真正將所有這些結(jié)合在一起的部分:我們需要從維基百科獲取一些數(shù)據(jù),將其解碼為Result
,將其頁(yè)面分配給我們的pages
屬性,然后設(shè)置loadingState
為.loaded
.?如果獲取失敗,我們將設(shè)置loadingState
為.failed
,SwiftUI 將加載適當(dāng)?shù)?UI。
警告:我們需要加載的維基百科 URL 非常長(zhǎng),因此與其嘗試輸入它,不如從文本或我的 GitHub gist 中復(fù)制粘貼:http:?//bit.ly/swiftwiki。
將此方法添加到EditView
:
該請(qǐng)求應(yīng)在視圖出現(xiàn)后立即開(kāi)始,因此task()
在現(xiàn)有修飾符之后添加此toolbar()
修飾符:
現(xiàn)在繼續(xù)并再次運(yùn)行該應(yīng)用程序——你會(huì)發(fā)現(xiàn)當(dāng)你放下圖釘時(shí),我們的EditView
屏幕會(huì)向上滑動(dòng)并向你顯示附近的所有地點(diǎn)。好的!



排序維基百科結(jié)果
維基百科的結(jié)果返回給我們的順序看起來(lái)可能是隨機(jī)的,但實(shí)際上是根據(jù)其內(nèi)部頁(yè)面 ID 排序的。但這對(duì)我們沒(méi)有幫助,這就是我們使用自定義閉包對(duì)結(jié)果進(jìn)行排序的原因。
很多時(shí)候,使用自定義排序功能正是你所需要的,但通常情況下,你的數(shù)據(jù)有一個(gè)自然順序——可能首先顯示最新的新聞故事,或者首先顯示聯(lián)系人的姓氏,等等。所以,而不是只需提供一個(gè)內(nèi)聯(lián)閉包給sorted()
,
我們就可以讓我們的Page
結(jié)構(gòu)符合Comparable
.?這實(shí)際上很容易做到,因?yàn)槲覀円呀?jīng)編寫(xiě)了排序代碼——只需將它移動(dòng)到我們的Page
結(jié)構(gòu)中即可。
因此,首先將結(jié)構(gòu)的定義修改為Page
:
如果你還記得,符合Comparable
只有一個(gè)要求:我們必須實(shí)現(xiàn)一個(gè)<
函數(shù),它接受我們結(jié)構(gòu)類(lèi)型的兩個(gè)參數(shù),如果第一個(gè)應(yīng)該在第二個(gè)之前排序,則返回 true。在這種情況下,我們可以直接將測(cè)試傳遞到title
字符串上,所以現(xiàn)在將此方法添加到Page
結(jié)構(gòu)中:
現(xiàn)在 Swift 知道如何對(duì)頁(yè)面進(jìn)行排序,它會(huì)自動(dòng)為我們提供sorted()
頁(yè)面數(shù)組上的無(wú)參數(shù)方法。這意味著當(dāng)我們?cè)O(shè)置fetchNearbyPlaces()
的
self.pages
時(shí)
我們現(xiàn)在可以添加sorted()
到末尾,如下所示:
在完成此屏幕之前,我們需要Text("Page description here")
用真實(shí)的東西替換視圖。維基百科的 JSON 數(shù)據(jù)確實(shí)包含一個(gè)描述,但它被埋沒(méi)了:terms
字典可能不在那里,如果它在那里它可能沒(méi)有description
鍵,如果它有鍵它可能是一個(gè)description
空數(shù)組而不是包含一些文本的數(shù)組里面。
我們不希望這種混亂困擾我們的 SwiftUI 代碼,因此最好的做法還是制作一個(gè)計(jì)算屬性,如果存在則返回描述,否則返回固定字符串。將其添加到Page
結(jié)構(gòu)中以完成它:
完成后,你可以替換Text("Page description here")
為:
這就完成了EditView
——它允許我們編輯注釋視圖的兩個(gè)屬性,它從維基百科下載和排序數(shù)據(jù),它根據(jù)網(wǎng)絡(luò)請(qǐng)求的進(jìn)行方式顯示不同的用戶界面,它甚至仔細(xì)查看維基百科內(nèi)容來(lái)決定什么可以是顯示。


