利用 SwiftUI 的 @EnvironmentObject 輕鬆地在視圖之間傳遞數據!


本篇原文(標題:Passing Variables to Other Views Made Easy With @EnvironmentObject)刊登於作者 Medium,由 Tatenda Kabike 所著,並授權翻譯及轉載。

我們在大部分的手機 App 中,都會看到整個 App 和視圖之間共享數據 (data) 的情況。SwiftUI 提供了一個方便又簡單的方法,讓我們在 App 中傳遞數據。在這篇文章中,我們將會試著使用 @EnvironmentObject,並仔細研究它的行為。

@EnvironmentObject 是一種物件型別 (object type),讓我們可以添加數據,之後再利用@StateObject 在 App 中隨時存取它,來添加信息或作出修改。

在這篇文章中,我將會利用一個簡單的例子,來示範如何使用 @EnvironmentObject 來傳遞數據。在這個範例中,我們會定義:

  1. UserSettings 類別,它包含了兩個 @published 屬性 (property):settinguserRole
  2. ViewSettings 視圖,用來在 Environment 接收 UserSetting 物件,並顯示 User Setting。
  3. ContentView 視圖,用來建立 UserSettings 物件,我們可以利用分段控制器 (segmented control) 來改變 User Settings。

以下是 UserSettings 的程式碼:

import Foundation

class UserSettings: ObservableObject {
    
    @Published var setting = 0
    @Published var userRole = 0
}

在上面的程式碼中,我們建立了一個符合 ObservableObject 的類別,及設定的數值,我們之後會在 App 中發佈和修改它們。

以下是 ViewSettings 的程式碼:

import Foundation
import SwiftUI

struct ViewSettings: View {
    
    @EnvironmentObject var settings: UserSettings
    
    var body: some View {
    
        Text("\(settings.userRole == 0 ? "User" : "Admin") is \(settings.setting == 0 ? "Active" : "Inactive" )")
    }
}

ViewSetting 視圖會利用 @EnvironmentObject 存取 UserSettings 類別,並使用它的屬性。

以下是 ContentView 的程式碼:

struct ContentView: View {
    
    @StateObject var settings = UserSettings()
    
    @State private var settingsTag = 0
    @State private var roleSettingsTag = 0
    
    @State private var active = "InActive"
    @State private var userRole = "User"
    @State private var selection = 2
    @State private var roleSelection = 1
    
    init() {
        UISegmentedControl.appearance().selectedSegmentTintColor = .systemPink
        UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
        UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.systemPink], for: .normal)
    }
    var body: some View {
     
        NavigationView {
            
          
            VStack {
            
                Picker("", selection: $settingsTag){
                    Text("Active").tag(0)
                    Text("InActive").tag(1)
                    
                }.onChange(of: settingsTag){_ in
                    
                    settings.setting = settingsTag
                }
                .padding()
                .pickerStyle(SegmentedPickerStyle())
                Text("\(settingsTag)")
               
                Divider()
                    .frame(height: 1)
               
                Picker("", selection: $roleSettingsTag){
                    Text("User").tag(0)
                    Text("Admin").tag(1)
                    
                }
                .onChange(of: roleSettingsTag){_ in
                  
                    settings.userRole = roleSettingsTag
                }
                .padding()
                .pickerStyle(SegmentedPickerStyle())
                
                Text("\(roleSettingsTag)")
                    
                
                Button(action: {
                    print(settings.setting)
                    print(settings.userRole)
                    
                   
                
                }) {
                    
                    NavigationLink(destination: ViewSettings()) {
                        
                
                    Text("View Settings")
                        .padding()
                        .foregroundColor(.white)
                        .background(Color.pink)
                        .cornerRadius(5)
                        .padding(.top, 30)
                        
                    }
                    
                }
            }
        
        }.environmentObject(settings)
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

以上的程式碼是範例的主視圖,也就是我們施展魔術的地方。

添加了以上的程式碼之後,主視圖看起來會是這樣:

EnvironmentObject

讓我簡單總結一下這個 App 的功能。我們宣告了 @StateObject 型別的 Settings 變數,我們會利用這個變數來修改和傳遞數據。來看看 onChange event 屬性,我們會在分段控制器中分配數值,而這些改動會被保存在 Settings 物件中。最重要的是,我們必須在父視圖 (parent view) 中添加 environmentObject,並添加想要設為 Environment Object 的物件;在我們這個範例中,就是 settings 變數。

在 View Settings 按鈕中,我們添加了導航連結 (link) 鏈接到下一個螢幕,在導航的時候,就能夠存取我們在 ViewSettings 視圖中修改後的數據。

完成了!我們成功把數據從 ContentView 視圖傳遞到 ViewSettings 視圖了。你可以在 GitHub 參考完整的程式碼。

本篇原文(標題:Passing Variables to Other Views Made Easy With @EnvironmentObject)刊登於作者 Medium,由 Tatenda Kabike 所著,並授權翻譯及轉載。

作者簡介:Tatenda Kabike,一位 iOS Mobile Developer 和 Content Creator。喜愛利用 ARKit 和 CoreML 來開發。離開電腦桌,我也喜歡旅遊和大自然。

譯者簡介:Kelly Chan-AppCoda 編輯小姐。


此文章為客座或轉載文章,由作者授權刊登,AppCoda編輯團隊編輯。有關文章詳情,請參考文首或文末的簡介。

blog comments powered by Disqus
Shares
Share This