日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SwiftUI之深入解析如何处理特定的数据和如何在视图中适配数据模型对象

發布時間:2024/5/21 编程问答 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SwiftUI之深入解析如何处理特定的数据和如何在视图中适配数据模型对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、前言

  • 閱讀了我的前兩篇博客的朋友,應該都熟練掌握了 SwiftUI 如何創建一個任何相關信息的展示視圖和各個視圖之間的相互組合,以及動態生成一個展示相關信息的可滾動列表,用戶可以點擊列表項去查看其相關的詳細信息。那么,當我們需要去標記相關的信息,亦或者過濾信息列表,只需要展示必要的相關信息,該怎么繼續處理呢?
    • 有關詳情視圖的創建和視圖的組合的示例,請參考我的博客:SwiftUI之深入解析如何創建和組合視圖;
    • 動態生成一個展示相關信息的可滾動列表,可以點擊查看其相關的詳細信息的示例,請參考我的博客:SwiftUI之深入解析如何創建列表展示視圖和列表如何導航跳轉新頁面。
  • 要增加這些特性,就比如以地圖上的地理位置和地點為例,我們需要在地點列表上添加一個開關,用來過濾用戶喜歡的地標,還需要在地標上添加一個星標按鈕,用戶可以點擊它來標記這個地標為自己喜歡的地點。

二、標記特定的數據

  • 標記用戶最喜歡的地標,給地標列表的每一行添加一個星標用來表示用戶是否標記該地標為自己喜歡的:

  • 打開工程項目,在項目導航下選擇 LandmarkRow.swift 文件,在空白占位后面添加一個 if 表達式,if 表達式判斷是否當前地標是用戶喜歡的,如果用戶標記當前地標為喜歡就顯示星標,可以在 SwitUI 的代碼塊中使用 if 語句來條件包含視圖;由于系統圖片是矢量類型的,可以使用 foregroundColor( _: ) 來改變它的顏色,當地標 landmark 的 isFavorite 屬性為真時,星標顯示;
struct LandmarkRow: View {var landmark : Landmarkvar body: some View {HStack {landmark.image.resizable().frame(width: 50, height: 50)Text(landmark.name)Spacer()if (landmark.isFavorite) {Image(systemName: "star.fill").imageScale(.medium).foregroundColor(.yellow)}}} }struct LandmarkRow_Previews: PreviewProvider {static var previews: some View {Group {LandmarkRow(landmark: landmarkData[0])LandmarkRow(landmark: landmarkData[1])}.previewLayout(.fixed(width: 300, height: 70))} }

三、過濾數據列表

  • 可以定制地標列表,讓它只顯示用戶喜歡的地標,或者顯示所有的地標,要實現這個功能,需要給 LandmarkList 視圖類型添加一些狀態變量,狀態(State)是一個值或者一個值的集合,會隨著時間而改變,同時會影響視圖的內容、行為或布局,在屬性前面加上 @State 修飾詞就是給視圖添加了一個狀態值:

  • 選擇 LandmarkList.swift 文件,并給 LandmarkList 添加一個名為 showFavoritesOnly 的狀態,初始值設置為 false;點擊 Resume 按鈕或快捷鍵 Command+Option+P 刷新畫布,當對視圖進行添加或修改屬性等結構性改變時,需要手動刷新畫布;
  • 代碼中通過檢查 showFavoritesOnly 屬性和每一個地標的 isFavorite 屬性值來過濾地標列表所展示的內容:
struct LandmarkList: View {@State var showFavoritesOnly : Bool = falsevar body: some View {NavigationView {List(landmarkData) { landmark inif !self.showFavoritesOnly || landmark.isFavorite {NavigationLink(destination: ContentView(landmark: landmark)) {LandmarkRow(landmark: landmark)}}}.navigationBarTitle(Text("Landmarks"))}} }

四、添加控件來切換狀態

  • 為了讓用戶控制地標列表的過濾器,需要添加一個可以修改 showFavoritesOnly 值的控件,傳遞一個綁定關系給 toggle 控件可以實現;一個綁定關系(binding)是對可變狀態的引用,當用戶點擊 toggle 控件,從開到關或從關到開,toggle 控件會通過綁定關系對應的更新視圖的狀態:

  • 創建一個嵌套的 ForEach 組來把地標數據轉換成地標行視圖,在一個列表中組合靜態和動態視圖,或者組合兩個甚至多個不同的動態視圖組,使用 ForEach 類型動態生成而不是給列表傳入數據集合生成列表視圖;
  • 添加一個 Toggle 視圖作為列表的每一個子視圖,傳入一個 showFavoritesOnly 的綁定關系,使用 $ 前綴來獲得一個狀態變量或屬性的綁定關系;
struct LandmarkList: View {@State var showFavoritesOnly : Bool = falsevar body: some View {NavigationView {List {Toggle(isOn: $showFavoritesOnly) {Text("Favorites only")}ForEach(landmarkData) { landmark inif !self.showFavoritesOnly || landmark.isFavorite {NavigationLink(destination: ContentView(landmark: landmark)) {LandmarkRow(landmark: landmark)}}}}.navigationBarTitle(Text("Landmarks"))}} }
  • 效果如下:

  • 實時預覽模式下,點擊 Toggle 控件來驗證過濾器的功能:

五、使用可觀察對象來存儲數據

  • 要實現用戶標記哪個地標為自己喜愛的地標這個功能,需要使用可觀察對象(observalble object)存放地標數據。可觀察對象是一種可以綁定到具體 SwifUI 視圖環境中的數據對象,SwiftUI 可以察覺它影響視圖展示的任何變化,并在這種變化發生后及時更新對應視圖的展示內容:

  • 創建一個名為 UserData.swift 的文件,聲明一個遵循 ObservableObject 協議的新數據模型,ObservableObject 協議來自響應式框架 Combine,SwiftUI 可以訂閱可觀察對象,并在數據發生改變時更新視圖的顯示內容;
  • 添加存儲屬性 showFavoritesOnly 和 landmarks,并賦予初始值,可觀察對象需要對外公布內部數據的任何改動,因此訂閱此可觀察對象的訂閱者就可以獲得對應的數據改動信息;
  • 給新建的數據模型的每一個屬性添加 @Published 屬性修飾詞:
import Combine import SwiftUIfinal class UserData: ObservableObject {@Published var showFavoritesOnly = false@Published var landmarks = landmarkData }

六、視圖中適配數據模型對象

  • 已經創建 UserData 可觀察對象,現在要改造視圖,讓它使用這個新的數據模型來存儲視圖內容數據:

  • 在 LandmarkList.swift 文件中,使用 @EnvironmentObject 修飾的 userData 屬性來替換原來的 showFavoritesOnly 狀態屬性,并對預覽視圖調用 environmentObject( _: ) 修改器,只要 environmentObject( _: ) 修改器應用在視圖的父視圖上,userData 就能夠自動獲取它的值;
  • 替換原來使用 showFavoritesOnly 狀態屬性的地方,改為使用 userData 中的對應屬性,與 @State 修飾的屬性一樣,也可以使用 $ 前綴訪問 userData 對象的成員綁定引用;
  • 創建 ForEach 實例時使用 userData.landmarks 做為數據源:
struct LandmarkList: View {@EnvironmentObject private var userData: UserDatavar body: some View {NavigationView {List {Toggle(isOn: $userData.showFavoritesOnly) {Text("Show Favorites Only")}ForEach(userData.landmarks) { landmark inif !self.userData.showFavoritesOnly || landmark.isFavorite {NavigationLink(destination: LandmarkDetail(landmark: landmark).environmentObject(self.userData)) {LandmarkRow(landmark: landmark)}}}}.navigationBarTitle(Text("Landmarks"))}} }struct LandmarksList_Previews: PreviewProvider {static var previews: some View {LandmarkList().environmentObject(UserData())} }

  • 在程序入口,對 LandmarkList 視圖調用 environmentObject 修改器,這樣可以把 UserData 的數據對象綁定到 LandmarkList 視圖的環境變量中,子視圖可以獲得父視圖環境中的變量,此時如果在模擬器或者真機上運行應用,也可以正常展示視圖內容:
@main struct HandlingUserInputApp: App {var body: some Scene {WindowGroup {LandmarkList().environmentObject(UserData())}} }
  • 更新 ContentView 視圖,讓它從父視圖的環境變量中取要展示的數據,之后在更新地標的用戶喜愛狀態時,會用到 landmarkIndex 這個變量:
struct ContentView: View {@EnvironmentObject var userData: UserDatavar landmark: Landmarkvar landmarkIndex: Int {userData.landmarks.firstIndex(where: { $0.id == landmark.id })!}var body: some View {VStack {MapView(coordinate: landmark.locationCoordinate).edgesIgnoringSafeArea(.top).frame(height: 300)CircleImage(image: landmark.image).offset(x: 0, y: -130).padding(.bottom, -130)VStack(alignment: .leading) {HStack {Text(landmark.name).font(.title)}HStack(alignment: .top) {Text(landmark.park).font(.subheadline)Spacer()Text(landmark.state).font(.subheadline)}}.padding()Spacer()}} }struct ContentView_Previews: PreviewProvider {static var previews: some View {let userData = UserData()return ContentView(landmark: landmarkData[0]).environmentObject(userData)} }
  • 切換到 LandmarkList.swift 文件,并打開實時預覽視圖去驗證所添加的功能是否正常工作。

七、為每一個地標創建一個喜愛按鈕

  • 可以在喜歡和不喜歡的地標列表間進行切換,但喜歡的地標列表還是硬編碼形成的,為了讓用戶可以自己標記哪個地標是自己喜歡的,需要在地標詳情頁添加一個標記喜歡的按鈕:

  • 在 ContentView.swift 的 HStack 中添加地標名稱的 Text,在地標名稱的 Text 控件旁邊添加一個新的按鈕控件,使用 if-else 條件語句設置不同的圖片顯示狀態表示這個地標是否被用戶標記為喜歡,在 Button 的動作閉包中,使用 landmarkIndex 去修改 userData 中對應地標的數據:

  • 切換到 landmarkList.swift,并開啟實時預覽模式,當從列表頁導航進入詳情頁后,點擊喜歡按鈕,喜歡的狀態會在返回列表頁后與列表中對應的地標喜歡狀態保持一致,因為列表頁和詳情頁的地標數據使用的是同一份,所以可以在不同頁面間保持狀態同步。
  • 完整示例:SwiftUI之如何處理特定的數據和如何在視圖中適配數據模型對象。

總結

以上是生活随笔為你收集整理的SwiftUI之深入解析如何处理特定的数据和如何在视图中适配数据模型对象的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。