最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

SwiftUI學(xué)習(xí)100天(Day60 - 里程碑:項(xiàng)目 10-12)

2023-03-05 12:00 作者:愛上樹の蝸牛  | 我要投稿

原創(chuàng)鏈接:https://www.hackingwithswift.com/100/swiftui

以下內(nèi)容僅供學(xué)習(xí)參考:?

這是完成的另外三個(gè)項(xiàng)目,以及更多真正重要的技術(shù)。無論你的設(shè)計(jì)多么漂亮或你的應(yīng)用創(chuàng)意多么聰明,處理好用戶數(shù)據(jù)幾乎始終是任何優(yōu)秀應(yīng)用最重要的事情。

當(dāng)然,真正討論的是“好”是什么意思。至少我希望這意味著“尊重”——未經(jīng)他們的同意,你不會分享任何東西,你不會在未經(jīng)許可的情況下跟蹤他們的活動,并且你會小心地存儲任何個(gè)人數(shù)據(jù)。除此之外,你可能想要添加搜索或過濾,你可能想要云同步以便他們的數(shù)據(jù)在設(shè)備之間共享,你可能想要讓他們?yōu)g覽或修改原始數(shù)據(jù),等等。

無論你用它做什么,學(xué)習(xí)使用用戶數(shù)據(jù)都是一項(xiàng)很好的技能,并且你在這最后三個(gè)項(xiàng)目中已經(jīng)向前邁進(jìn)了很多步。

現(xiàn)在是挑戰(zhàn)的時(shí)候了,毫不奇怪,它將涉及獲取、處理和顯示大量數(shù)據(jù)。你已經(jīng)具備了使這款應(yīng)用程序成為出色應(yīng)用程序所需的所有技能,所以剩下的就是讓你打開一個(gè)新的 Xcode 項(xiàng)目并投入其中。

你會犯錯(cuò)嗎?是的——沒關(guān)系。英國作家尼爾·蓋曼 (Neil Gaiman) 提出了一些建議,希望對你有所幫助:

我希望在接下來的一年里,你會犯錯(cuò)誤。因?yàn)槿绻阍诜稿e(cuò)誤,那么你就是在創(chuàng)造新事物、嘗試新事物、學(xué)習(xí)、生活、推動自己、改變自己、改變你的世界。你正在做你以前從未做過的事情,更重要的是,你正在做一些事情。

今天你有三個(gè)主題要完成,其中之一是你的挑戰(zhàn)。


你學(xué)到了什么

這最后三個(gè)項(xiàng)目確實(shí)在數(shù)據(jù)上施加了很大的壓力,首先是使用互聯(lián)網(wǎng)發(fā)送和接收數(shù)據(jù),然后進(jìn)入核心數(shù)據(jù),這樣你就可以看到真正的應(yīng)用程序是如何管理它們的數(shù)據(jù)的。你在這個(gè)項(xiàng)目中學(xué)到的技能可能比你意識到的更重要,因?yàn)槿绻惆阉鼈兎旁谝黄?,你現(xiàn)在可以從 Internet 獲取數(shù)據(jù),將其存儲在本地,并讓用戶過濾以找到他們關(guān)心的東西。

以下是我們在過去三個(gè)項(xiàng)目中涵蓋的所有新事物的快速回顧:

  • 構(gòu)建自定義Codable一致性

  • 使用URLSession發(fā)送和接收數(shù)據(jù)

  • disabled()視圖修飾符

  • 使用構(gòu)建自定義 UI 組件@Bindable

  • 向警報(bào)alert彈窗添加多個(gè)按鈕

  • SwiftUI中如何使用Swift的Hashable協(xié)議

  • 使用@FetchRequest屬性包裝器查詢核心數(shù)據(jù)

  • 使用SortDescriptor排序核心數(shù)據(jù)結(jié)果

  • 創(chuàng)建自定義NSManagedObject子類

  • 使用過濾數(shù)據(jù)NSPredicate

  • 創(chuàng)建核心數(shù)據(jù)實(shí)體之間的關(guān)系

與其他一些項(xiàng)目相比,這是一個(gè)相對較短的列表,但我認(rèn)為可以公平地說這些主題是一個(gè)真正的進(jìn)步:核心數(shù)據(jù)在某些地方很難,特別是我們需要如何橋接NSSet諸如此類的東西以便它們在光明和SwiftUI 的未來。

關(guān)鍵點(diǎn)

盡管我們在最后三個(gè)項(xiàng)目中涵蓋了很多內(nèi)容,但我特別想更詳細(xì)地介紹兩件事:類型擦除和Codable.?我們已經(jīng)在我們的項(xiàng)目中對這些進(jìn)行了一些研究,但正如你將看到的那樣,它們還需要一些額外的時(shí)間……

返回不同的視圖

SwiftUI 的視圖只有一個(gè)要求,即它們具有body返回某種特定類型視圖的屬性。正如我們在早期的技術(shù)項(xiàng)目中看到的那樣,指定精確的返回類型是痛苦的,因?yàn)?SwiftUI 在我們應(yīng)用修飾符時(shí)構(gòu)建容器的方式,這就是為什么我們有some View– “這將返回一種特定類型的視圖,但我們不會想說什么?!?/p>

然而,Swift 做了一些非常聰明的事情來幫助我們的生活更輕松:它自動將@ViewBuilder屬性添加到所有?SwiftUI?視圖的body屬性中。這只發(fā)生在body上,而不是任何返回some?View的屬性上,但它無聲地增加了一個(gè)重要的超能力:我們可以返回多個(gè)視圖,并且也可以根據(jù)條件返回不同的視圖。

但是,由于其他屬性默認(rèn)情況下無法訪問此超級功能:它們有時(shí)無法返回文本視圖,有時(shí)無法返回圖像,但由于 SwiftUI 使用修飾符容器包裝視圖的方式,這甚至意味著它們無法混合并匹配許多修飾符。

所以,這樣的代碼是無效的:

(注意:出于演示目的,我已將代碼放入randomText;顯然,在實(shí)際項(xiàng)目中,你要么在視圖的其他地方有更多代碼,要么將其直接放入body.)

我們有多種方法可以解決這個(gè)問題:

  • 我們可以將我們的視圖包裝在另一個(gè)名為 AnyView的視圖中,它使用類型擦除來隱藏其內(nèi)容。

  • 我們可以手動將@ViewBuilder注釋添加到其他屬性。

  • 我們可以將代碼包裝在一個(gè)Group中的屬性內(nèi),這意味著只返回一個(gè)視圖。

  • 使用三元條件運(yùn)算符提供不同的值。

我想逐一介紹這些選項(xiàng),以便你了解它們的外觀以及它們的比較方式。

類型擦除是隱藏某些數(shù)據(jù)的底層類型的過程。這在 Swift 中經(jīng)常使用:我們有類型擦除包裝器,例如AnyHashableAnySequence,它們所做的只是充當(dāng)外殼,將它們的操作轉(zhuǎn)發(fā)到它們包含的任何內(nèi)容,而不會向任何外部透露內(nèi)容。

在 SwiftUI 中我們有AnyView這個(gè)目的:它可以在其中容納任何類型的視圖,這允許我們自由地混合和匹配視圖,如下所示:

然而,使用 AnyView有性能成本:通過隱藏我們的視圖結(jié)構(gòu)方式,我們迫使 SwiftUI 在我們的視圖層次結(jié)構(gòu)發(fā)生變化時(shí)做更多的工作——如果我們在類型擦除的部分之一中進(jìn)行一個(gè)小的更改我們的視圖層次結(jié)構(gòu),很有可能都需要重新創(chuàng)建。

就像我說的,有其他選擇,其中之一是在需要的@ViewBuilder任何地方手動添加屬性,如下所示:

有了它,我們不再需要AnyViewreturn關(guān)鍵字,因?yàn)樗坑?@ViewBuilder 處理——我們已經(jīng)使randomText屬性像body.

有很多地方使用@ViewBuilder是一個(gè)很好的解決方案,包括需要返回非常不同類型的視圖的地方。但是,請不要濫用它:如果你發(fā)現(xiàn)自己需要經(jīng)常使用@ViewBuilder,這可能意味著你試圖將太多邏輯塞進(jìn)你的 SwiftUI 視圖中,并且很有可能你會通過將它們分割成更小的視圖來做得更好.

另一種選擇是使用Grouper而不是@ViewBuilder,如下所示:

老實(shí)說,這與使用@ViewBuilder沒什么不同.?是的,在幕后有一個(gè)額外的 SwiftUI 視圖在起作用(Group視圖),但它不會對布局產(chǎn)生影響,而且那個(gè)額外的視圖可能只是被優(yōu)化掉了。

最后一個(gè)選項(xiàng)并不總是可行的,但在這里是可行的,你應(yīng)該始終注意它:在你可以使用它的地方,三元條件運(yùn)算符始終是比上述任何解決方案更好的選擇。

SwiftUI 的許多修飾符(包括frame())允許我們傳遞nil而不是值,這會導(dǎo)致修飾符不執(zhí)行任何操作。其他一些修飾符,如blur()opacity()不允許nil被傳遞,但你也可以提供不執(zhí)行任何操作的默認(rèn)值 –?例如,blur(radius: 0)opacity(1)這些被稱為惰性修飾符,SwiftUI 只會在布局結(jié)果之前刪除它們。

所以,我們代碼的理想版本是這樣的:

為什么是“理想”?因?yàn)樵谶@種情況下 SwiftUI 只創(chuàng)建一個(gè)文本視圖。是的,寬度在固定的 300 點(diǎn)和文本的默認(rèn)大小之間變化,但創(chuàng)建的實(shí)際渲染文本沒有變化。相比之下,使用AnyView、@ViewBuilderGroup所有涉及兩個(gè)視圖:當(dāng)Bool.random()值從一個(gè)狀態(tài)翻轉(zhuǎn)到另一個(gè)狀態(tài)時(shí),第一個(gè)文本視圖將被銷毀并創(chuàng)建一個(gè)新視圖。

至少有一次你真的需要AnyView的類型擦除能力,但它真的應(yīng)該是你最后的選擇。例如,你不能創(chuàng)建一個(gè)組數(shù)組,因?yàn)?strong>[Group]它本身沒有任何意義——SwiftUI 想知道數(shù)組中有什么。另一方面,[AnyView]完全沒問題,因?yàn)?span id="s0sssss00s" class="color-pink-02">AnyView內(nèi)容無關(guān)緊要。

所以,這種代碼只有在實(shí)際類型擦除時(shí)才有可能:

每次點(diǎn)擊按鈕時(shí),都會將一個(gè)形狀添加到數(shù)組中,但由于ShapeGroup都沒有意義,因此必須鍵入數(shù)組[AnyView]。

如果你打算定期使用類型擦除,那么添加這個(gè)方便的擴(kuò)展是值得的:

通過這種方法,我們可以把erasedToAnyView()像修飾符一樣對待:

作為非常粗略的指導(dǎo),你應(yīng)該:

  1. 旨在使用三元條件運(yùn)算符而不是使用if條件。

  2. 寧愿將大視圖分解成更小的視圖,也不要在視圖層次結(jié)構(gòu)中添加復(fù)雜的邏輯。

  3. 使用Group避免 10個(gè)視圖的限制,或在其他情況下不可能的地方添加修飾符,例如navigationTitle()。

  4. 僅對簡單的屬性使用顯式@ViewBuilder,但當(dāng)新視圖可能更有意義時(shí),請謹(jǐn)慎使用它來掩蓋復(fù)雜的邏輯。

  5. 如果其他選項(xiàng)都不起作用,則退而求其次使用AnyView。

編碼鍵

當(dāng)我們擁有與我們設(shè)計(jì)類型的方式相匹配的 JSON 數(shù)據(jù)時(shí),就Codable可以完美地工作。事實(shí)上,如果我們不使用諸如 @Published之類的屬性包裝器,我們通常不需要做任何事情,除了添加Codable一致性之外——Swift 編譯器會自動合成我們需要的一切。

然而,很多時(shí)候事情并不是那么簡單。在這些情況下,我們可能需要編寫自定義Codable一致性——即,手寫init(from:)——encode(to:)但有一個(gè)中間地帶,在一些指導(dǎo)下,Codable仍然可以為我們完成大部分工作。

一個(gè)常見的例子是我們傳入的 JSON 對其屬性使用不同的命名約定。例如,我們可能會收到蛇形大小寫的 JSON 屬性名稱(例如first_name),而我們的 Swift 代碼使用駝峰大小寫的屬性名稱(例如firstName)。Codable只要它知道期望什么,它就能夠在這兩者之間進(jìn)行轉(zhuǎn)換——我們需要在我們的解碼器上設(shè)置一個(gè)名為keyDecodingStrategy.

為了證明這一點(diǎn),這里有一個(gè)User具有兩個(gè)屬性的結(jié)構(gòu):

下面是一些具有相同兩個(gè)屬性的 JSON 數(shù)據(jù),但使用蛇形大小寫:

如果我們嘗試將該 JSON 解碼為一個(gè)User實(shí)例,它將不起作用:

但是,如果我們在調(diào)用之前修改密鑰解碼策略decode(),我們可以要求 Swift 將蛇形大小寫與駝峰大小寫相互轉(zhuǎn)換。所以,這會成功:

當(dāng)我們將 snake_case 與 camelCase 相互轉(zhuǎn)換時(shí)效果很好,但如果我們的數(shù)據(jù)完全不同怎么辦?

例如,看一下這個(gè) JSON:

它仍然有用戶的名字和姓氏,但屬性名稱與我們的結(jié)構(gòu)完全不匹配。

當(dāng)我們查看Codable時(shí),我說過我們可以創(chuàng)建一個(gè)編碼密鑰枚舉,描述哪些密鑰應(yīng)該被編碼和解碼。當(dāng)時(shí)我說“這個(gè)枚舉通常被稱為CodingKeys,末尾有一個(gè) S,但如果你愿意,你可以稱它為其他東西”,雖然這是真的,但這不是全部。

你看,我們通常使用CodingKeys名稱的原因是這個(gè)名稱具有超能力:如果CodingKeys存在枚舉,Swift 將自動使用它來決定如何在我們不提供自定義Codable實(shí)現(xiàn)的情況下對對象進(jìn)行編碼和解碼。

我意識到要接受的內(nèi)容很多,所以最好用一些代碼來演示。嘗試將User結(jié)構(gòu)更改為此:

該代碼將編譯得很好,因?yàn)槊QZZZCodingKeys對 Swift 沒有意義——它只是一個(gè)嵌套的枚舉。但是,如果你將枚舉重命名為CodingKeys,你會發(fā)現(xiàn)代碼不再構(gòu)建:我們現(xiàn)在指示 Swift 只對firstName屬性進(jìn)行編碼和解碼,這意味著沒有初始化器來處理設(shè)置lastName屬性——這是不允許的。

所有這些都很重要,因?yàn)?span id="s0sssss00s" class="color-pink-02">CodingKeys它有第二個(gè)超能力:如果我們將原始值字符串附加到我們的屬性,Swift 將使用它們作為 JSON 屬性名稱。也就是說,case 名稱應(yīng)該與我們的 Swift 屬性名稱相匹配,case值應(yīng)該與 JSON 屬性名稱相匹配。

那么,讓我們回到我們的示例 JSON:

它使用“first”和“l(fā)ast”作為屬性名稱,而我們的User結(jié)構(gòu)體使用的是firstNamelastName。這是CodingKeys可以解決問題的一個(gè)好地方:我們不需要編寫自定義Codable一致性,因?yàn)槲覀冎恍杼砑訉?Swift 屬性名稱與 JSON 屬性名稱結(jié)合起來的編碼鍵,如下所示:

既然我們已經(jīng)明確告訴 Swift 如何在 JSON 和 Swift 命名之間轉(zhuǎn)換,我們就不再需要使用了keyDecodingStrategy——只需要添加那個(gè)枚舉就足夠了。

因此,雖然你確實(shí)需要知道如何創(chuàng)建自定義Codable一致性,但如果這些其他選項(xiàng)可行,通常最好不要使用它。

挑戰(zhàn)

現(xiàn)在是你從頭開始構(gòu)建應(yīng)用程序的時(shí)候了,今天這是一個(gè)特別廣泛的挑戰(zhàn):你的工作是使用URLSession從互聯(lián)網(wǎng)上下載一些 JSON,使用Codable將其轉(zhuǎn)換為 Swift 類型,然后使用NavigationView、List等將其顯示到用戶。

你的第一步應(yīng)該是檢查 JSON。你使用的 URL 是:https?://www.hackingwithswift.com/samples/friendface.json – 這是大量隨機(jī)生成的用戶數(shù)據(jù)集合。

如你所見,有一個(gè)人數(shù)組,每個(gè)人都有一個(gè) ID、姓名、年齡、電子郵件地址等。他們還有一組標(biāo)簽字符串和一組朋友,其中每個(gè)朋友都有一個(gè)名字和 ID。

你實(shí)現(xiàn)它的程度取決于你,但至少你應(yīng)該:

  • 獲取數(shù)據(jù)并將其解析為UserFriend結(jié)構(gòu)。

  • 顯示一個(gè)用戶列表,其中包含一些關(guān)于他們的信息,例如他們的姓名以及他們現(xiàn)在是否活躍。

  • 創(chuàng)建點(diǎn)擊用戶時(shí)顯示的詳細(xì)信息視圖,顯示有關(guān)他們的更多信息,包括他們朋友的名字。

  • 在開始下載之前,請檢查你的User數(shù)組是否為空,這樣你就不會在每次顯示視圖時(shí)都繼續(xù)開始下載。

如果你不確定從哪里開始,請先設(shè)計(jì)你的類型:構(gòu)建一個(gè)具有name、agecompany等屬性的User結(jié)構(gòu)體,然后構(gòu)建一個(gè)具有idnameFriend結(jié)構(gòu)。之后,轉(zhuǎn)到一些URLSession代碼來獲取數(shù)據(jù)并將其解碼為你的類型。

你可能會注意到每個(gè)用戶注冊的日期都有一個(gè)非常特定的格式:2015-11-10T01:47:18-00:00。這被稱為 ISO-8601,它是如此普遍以至于有一個(gè)內(nèi)置的dateDecodingStrategy調(diào)用.iso8601可以自動解碼它。

在你構(gòu)建此應(yīng)用程序時(shí),我希望你牢記一件事:此類應(yīng)用程序是 iOS 應(yīng)用程序開發(fā)的基礎(chǔ)——如果你能自信地搞定這一點(diǎn),那么你就已經(jīng)走上了全面發(fā)展的道路——作為應(yīng)用程序開發(fā)人員的時(shí)間工作。

提示:一如既往,解決這一挑戰(zhàn)的最佳方法是保持簡單——編寫盡可能少的代碼來解決挑戰(zhàn),并且讓你對它運(yùn)行良好感到滿意。


SwiftUI學(xué)習(xí)100天(Day60 - 里程碑:項(xiàng)目 10-12)的評論 (共 條)

分享到微博請遵守國家法律
南投县| 乃东县| 阿巴嘎旗| 镇雄县| 道真| 成都市| 郑州市| 丹阳市| 怀来县| 扎兰屯市| 武山县| 禄丰县| 邹平县| 大安市| 白银市| 延吉市| 科技| 安阳县| 河北省| 嘉祥县| 台湾省| 梁山县| 贵南县| 射阳县| 炉霍县| 和龙市| 宁安市| 望城县| 唐山市| 武宁县| 黄骅市| 三明市| 惠州市| 富川| 偏关县| 金门县| 治县。| 贞丰县| 房山区| 穆棱市| 读书|