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

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

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

2023-03-10 12:00 作者:愛(ài)上樹(shù)の蝸牛  | 我要投稿

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

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

今天,我們將練習(xí)你剛學(xué)到的一些技術(shù),包括如何創(chuàng)建自定義綁定、如何在 SwiftUI 中進(jìn)行包裝以供使用PHPickerViewController,以及如何將 Core Filter 效果應(yīng)用于圖像。

我希望你注意到的一件事是我如何經(jīng)常引導(dǎo)你回到我們之前研究過(guò)的主題。這不是偶然的:正如自助作家拿破侖希爾所寫(xiě)的那樣,“任何想法、計(jì)劃或目的都可以通過(guò)思想的重復(fù)出現(xiàn)在腦海中”——這種重復(fù)是我用來(lái)幫助你內(nèi)化的幾種方法之一所有這些代碼如何組合在一起。

即使你今天沒(méi)有完全理解這些概念,也沒(méi)關(guān)系——我們將來(lái)會(huì)再次介紹它們。

今天你要完成三個(gè)主題,在這些主題中你將練習(xí)包裝一個(gè)UIViewController以用于 SwiftUI,使用 Core Image 過(guò)濾圖像,等等。

構(gòu)建我們的基本 UI

我們項(xiàng)目的第一步是構(gòu)建基本的用戶界面,這個(gè)應(yīng)用程序?qū)⑹牵?br>

  1. 一個(gè)NavigationView,這樣我們就可以在頂部顯示我們應(yīng)用程序的名稱。

  2. 一個(gè)大的灰色框,上面寫(xiě)著“點(diǎn)擊以選擇圖片”,我們將在其上放置他們導(dǎo)入的圖片。

  3. “強(qiáng)度”滑塊將影響我們應(yīng)用 Core Image 過(guò)濾器的強(qiáng)度,存儲(chǔ)為 0.0 到 1.0 之間的值。

  4. “保存”按鈕將修改后的圖像寫(xiě)入用戶的照片庫(kù)。

最初用戶不會(huì)選擇圖像,因此我們將使用@State可選的圖像屬性來(lái)表示它。

首先將這兩個(gè)屬性添加到ContentView

現(xiàn)在將其body屬性的內(nèi)容修改為:

我喜歡能夠在 SwiftUI 布局中放置可選視圖,而且我認(rèn)為它特別適合ZStack因?yàn)楫?dāng)用戶加載圖片時(shí),圖片下方的文本會(huì)自動(dòng)被遮擋。

現(xiàn)在,由于我們的代碼在這里相當(dāng)簡(jiǎn)單,我想簡(jiǎn)單地探討一下清理我們的body財(cái)產(chǎn)的樣子——我們有很多布局代碼,但正如你所看到的,我們還有幾個(gè)按鈕關(guān)閉也在那里。

對(duì)于非常小的代碼片段,我通常很樂(lè)意將按鈕操作指定為閉包,但是當(dāng)我們完成后,保存按鈕將有很多行,所以我建議將它分解成它自己的函數(shù).

現(xiàn)在這只是意味著向 ContentView中添加一個(gè)空save()方法,如下所示:

然后我們會(huì)像這樣從按鈕調(diào)用它:

當(dāng)你學(xué)習(xí)時(shí),直接在你的視圖中編寫(xiě)按鈕操作和類似操作是很常見(jiàn)的,但是一旦你開(kāi)始真正的項(xiàng)目,花額外的時(shí)間來(lái)清理你的代碼是個(gè)好主意——從長(zhǎng)遠(yuǎn)來(lái)看,這會(huì)讓你的生活更輕松,相信我!

我將在以后添加更多像這樣的小清理技巧,因此當(dāng)你開(kāi)始接近課程的結(jié)尾時(shí),你會(huì)越來(lái)越相信你的代碼狀態(tài)良好。

使用 PHPickerViewController 將圖像導(dǎo)入 SwiftUI

為了使這個(gè)項(xiàng)目栩栩如生,我們需要讓用戶從他們的圖庫(kù)中選擇一張照片,然后將其顯示在ContentView.?我已經(jīng)向你展示了這一切是如何工作的,所以如果你按照介紹性章節(jié)進(jìn)行操作,你將已經(jīng)擁有所需的大部分代碼。

如果你錯(cuò)過(guò)了這些章節(jié),現(xiàn)在還為時(shí)不晚:創(chuàng)建一個(gè)名為 ImagePicker.swift 的新 Swift 文件,然后將其代碼替換為:

這是我們之前看過(guò)的所有代碼,所以我不打算重新解釋它們的作用。相反,我想回到 ContentView.swift 以便我們可以使用它。

首先,我們需要一個(gè)@State布爾值來(lái)跟蹤我們的圖像選擇器是否正在顯示,因此首先將其添加到ContentView

其次,我們需要在點(diǎn)擊灰色大矩形時(shí)將該布爾值設(shè)置為 true,因此將// select an image注釋替換為:

第三,我們需要一個(gè)屬性來(lái)存儲(chǔ)用戶選擇的圖像。我們?yōu)樵?span id="s0sssss00s" class="color-pink-02">ImagePicker結(jié)構(gòu)提供了一個(gè)@Binding附加到UIImage的屬性,這意味著當(dāng)我們創(chuàng)建圖像選擇器時(shí),我們需要傳入 UIImage以便它鏈接到。當(dāng)@Binding屬性改變時(shí),外部值也會(huì)改變,這讓我們可以讀取值。

因此,將此屬性添加到ContentView

第四,我們需要一個(gè)在ImagePicker視圖被關(guān)閉時(shí)調(diào)用的方法。現(xiàn)在這只是將選定的圖像直接放入 UI,所以請(qǐng)將此方法添加到ContentView現(xiàn)在:

然后,只要我們的inputImage值發(fā)生變化,我們就可以調(diào)用它,通過(guò)在ContentView某處附加一個(gè)onChange()修飾符——它在哪里真的不重要,但在navigationTitle()之后似乎是明智的。

最后,我們需要在ContentView某處添加一個(gè)修飾符在sheet()。這將showingImagePicker用作它的條件,并呈現(xiàn)一個(gè)ImagePicker綁定到inputImage作為它的內(nèi)容。

因此,將其直接添加到現(xiàn)有navigationTitle()修飾符下方:

這就完成了包裝 UIKit 視圖控制器以便在 SwiftUI 中使用所需的所有步驟。這次我們過(guò)得更快了一點(diǎn),但希望它仍然有意義!

繼續(xù)并再次運(yùn)行該應(yīng)用程序,你應(yīng)該能夠點(diǎn)擊灰色矩形來(lái)導(dǎo)入圖片,當(dāng)你找到一張圖片時(shí),它將出現(xiàn)在我們的 UI 中。

提示:我們剛剛制作的ImagePicker視圖是完全可重用的——你可以將 Swift 文件放在一邊,然后輕松地在其他項(xiàng)目中使用它。如果你考慮一下,包裝視圖的所有復(fù)雜性都包含在 ImagePicker.swift 中,這意味著如果你選擇在其他地方使用它,只需顯示一個(gè)工作表并綁定一個(gè)圖像即可。


使用 Core Image 進(jìn)行基本圖像過(guò)濾

現(xiàn)在我們的項(xiàng)目有用戶選擇的圖像,下一步是讓用戶對(duì)其應(yīng)用不同的 Core Image 濾鏡。首先,我們將只使用一個(gè)過(guò)濾器,但很快我們將使用確認(rèn)對(duì)話框?qū)ζ溥M(jìn)行擴(kuò)展。

如果我們想在我們的應(yīng)用程序中使用 Core Image,我們首先需要在 ContentView.swift 的頂部添加兩個(gè)導(dǎo)入:

接下來(lái)我們需要上下文和過(guò)濾器。Core Image 上下文是一個(gè)負(fù)責(zé)將一個(gè)CIImage渲染到 一個(gè)CGImage的對(duì)象,或者更實(shí)際地說(shuō),是一個(gè)將圖像的配方轉(zhuǎn)換為我們可以使用的實(shí)際像素系列的對(duì)象。

創(chuàng)建上下文的成本很高,因此如果你打算渲染許多圖像,最好創(chuàng)建一次上下文并使其保持活動(dòng)狀態(tài)。至于過(guò)濾器,我們將使用CIFilter.sepiaTone()默認(rèn)值,但因?yàn)槲覀兩院髸?huì)使其靈活,所以我們將使用過(guò)濾器@State,以便可以更改它。

因此,將這兩個(gè)屬性添加到ContentView

有了這兩個(gè),我們現(xiàn)在可以編寫(xiě)一個(gè)方法來(lái)處理導(dǎo)入的任何圖像——這意味著它將根據(jù)中的值設(shè)置我們的棕褐色過(guò)濾器的強(qiáng)度filterIntensity,從過(guò)濾器中讀取輸出圖像,要求CIContext渲染它,然后將結(jié)果放入我們的image屬性中,以便在屏幕上可見(jiàn)。

提示:可悲的是,棕褐色調(diào)濾鏡背后的核心圖像想要Float而不是Double它的值。這讓 Core Image 感覺(jué)更老了,我知道,但別擔(dān)心——我們很快就會(huì)讓它消失!

接下來(lái)的工作是改變工作方式loadImage()。現(xiàn)在分配給image屬性,但我們不再需要它了。相反,它應(yīng)該將選擇的任何圖像發(fā)送到棕褐色調(diào)過(guò)濾器中,然后調(diào)用applyProcessing()使魔法發(fā)生。

Core Image 濾鏡有一個(gè)專用inputImage屬性,讓我們可以發(fā)送一個(gè)CIImage用于濾鏡使用的屬性,但通常這會(huì)被徹底破壞并導(dǎo)致你的應(yīng)用程序崩潰——使用setValue()帶有鍵的濾鏡方法要安全得多kCIInputImageKey

所以,loadImage()用這個(gè)替換你現(xiàn)有的方法:

如果你現(xiàn)在運(yùn)行代碼,你會(huì)看到我們的基本應(yīng)用程序流程運(yùn)行良好:我們可以選擇一個(gè)圖像,然后查看應(yīng)用了棕褐色效果的圖像。但是我們添加的那個(gè)強(qiáng)度滑塊不會(huì)做任何事情,即使它綁定到filterIntensity我們的過(guò)濾器正在讀取的相同值。

這里發(fā)生的事情應(yīng)該不會(huì)太令人驚訝:即使滑塊正在更改 filterIntensity的值,更改該屬性也不會(huì)自動(dòng)applyProcessing()再次觸發(fā)我們的方法。相反,我們需要通過(guò)告訴 SwiftUI?filterIntensity使用onChange().

同樣,這些onChange()修飾符可以在我們的 SwiftUI 視圖層次結(jié)構(gòu)中的任何位置,但在這種情況下我做了一些不同的事情:當(dāng)一個(gè)特定的視圖負(fù)責(zé)更改一個(gè)值時(shí),我通常會(huì)將onChange()直接添加到該視圖,這樣我以后就可以清楚地調(diào)整視圖引發(fā)副作用。如果多個(gè)視圖調(diào)整相同的值,或者如果不是很具體是什么在改變值,那么我會(huì)在視圖的末尾添加修飾符。

無(wú)論如何,這里filterIntensity正在被滑塊改變,所以讓我們?cè)?span id="s0sssss00s" class="color-pink-02">onChange()那里添加:

你現(xiàn)在可以繼續(xù)運(yùn)行該應(yīng)用程序,但要注意:盡管 Core Image 在所有 iPhone 上都非???,但在模擬器中通常非常慢。這意味著你可以嘗試確保一切正常,但如果你的代碼運(yùn)行速度與攜帶沉重購(gòu)物袋的哮喘螞蟻一樣快,請(qǐng)不要感到驚訝。



SwiftUI學(xué)習(xí)100天(Day65 - 項(xiàng)目 13,第四部分)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
伊金霍洛旗| 宝山区| 扶风县| 武城县| 浙江省| 麻城市| 萍乡市| 宁城县| 盐城市| 商河县| 商城县| 铁岭县| 东宁县| 马鞍山市| 于都县| 利川市| 永修县| 集贤县| 赤壁市| 呼伦贝尔市| 高淳县| 上杭县| 怀远县| 白山市| 曲沃县| 嘉义县| 新和县| 广南县| 黄浦区| 彰化县| 聂拉木县| 漳浦县| 高碑店市| 甘孜| 鹤庆县| 万全县| 类乌齐县| 宁安市| 谢通门县| 沧州市| 岐山县|