SwiftUI 全局 Loading 实现指南

随着 SwiftUI 的广泛应用,开发者越来越倾向于使用 SwiftUI 来构建用户界面。其中一个常见需求就是实现全局 loading 状态的功能。本文将为你详细解析如何在 SwiftUI 中实现全局 loading 的效果。

流程概述

在实现全局 loading 功能前,我们首先需要明确整个实施过程的步骤。以下是实现的整体流程:

步骤 描述
1 创建 Loading View 组件
2 创建 GlobalState 以维护 loading 状态
3 在根视图中引用 GlobalState 并观察变化
4 在需要 loading 状态的部分使用 Loading View
5 完善 Demo 进行测试

详细步骤

1. 创建 Loading View 组件

首先,我们需要创建一个 reusable Loading View 组件,方便在各个地方使用。

import SwiftUI

struct LoadingView: View {
    var body: some View {
        // 使用 ZStack 居中显示 loading 界面
        ZStack {
            Color.black.opacity(0.4) // 背景色为半透明黑色
                .ignoresSafeArea()
            ProgressView("加载中...") // 显示加载中的进度条
                .padding(20)
                .background(Color.white) // 背景为白色
                .cornerRadius(10)
        }
    }
}

代码解析: LoadingView 使用了 ZStack 来布局,保证 loading 界面的内容在屏幕中央。

2. 创建 GlobalState 以维护 loading 状态

接下来,我们需要一个类来维护全局的 loading 状态。我们可以使用 ObservableObject 来实现这一点。

import SwiftUI
import Combine

class GlobalState: ObservableObject {
    @Published var isLoading: Bool = false // 定义一个发布的变量 isLoading
}

代码解析: 我们创建了一个名为 GlobalState 的类,里面有一个 @Published 属性 isLoading,用来表示当前 loading 是否开启。

3. 在根视图中引用 GlobalState 并观察变化

现在,我们需要在应用的根视图中实例化 GlobalState,并观察 isLoading 的变化。

@main
struct MyApp: App {
    @StateObject private var globalState = GlobalState() // 初始化全局状态

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(globalState) // 将 globalState 提供给子视图使用
        }
    }
}

代码解析: @StateObject 用于创建一个全局的状态对象,并将其作为环境对象传递给所有子视图。

4. 在需要 loading 状态的部分使用 Loading View

在需要展示 loading 的地方(例如网络请求前后),我们可以根据 isLoading 的值来显示或隐藏 LoadingView

struct ContentView: View {
    @EnvironmentObject var globalState: GlobalState // 获取环境对象

    var body: some View {
        VStack {
            Button(action: {
                toggleLoading() // 点击按钮时切换 loading 状态
            }) {
                Text("切换加载状态")
            }
        }
        .overlay(
            globalState.isLoading ? LoadingView() : nil // 根据 isLoading 的状态来决定是否显示 loading
        )
    }

    private func toggleLoading() {
        globalState.isLoading.toggle() // 切换 loading 状态
    }
}

代码解析:ContentView 中,我们用 overlay 来根据 isLoading 的值决定是否显示 LoadingView

5. 完善 Demo 进行测试

在 Visual Studio Code 或 Xcode 中运行你的应用,点击按钮可以看到 loading 的效果。你可以扩展功能,例如在网络请求开始时自动设置 loading 状态。

甘特图

gantt
    title 全局 Loading 实现时间安排
    dateFormat  YYYY-MM-DD
    section 准备工作
    创建 Loading View          :a1, 2023-10-01, 1d
    创建 GlobalState           :after a1  , 1d
    section 实现工作
    在根视图中设置 GlobalState :2023-10-03  , 1d
    使用 Loading View           :after a1  , 1d
    完善 Demo                   :after a1  , 2d

序列图

sequenceDiagram
    participant User
    participant App
    participant GlobalState
    participant LoadingView

    User->>App: 点击切换按钮
    App->>GlobalState: 调用 toggleLoading()
    GlobalState->>App: 更新 isLoading 状态
    App->>LoadingView: 显示或隐藏 LoadingView

结语

本文详细介绍了在 SwiftUI 中实现全局 loading 状态的步骤,从创建 Loading View 组件到维护 loading 状态的 GlobalState,再到在视图中处理 loading 的显示。通过实例的演示,您应该基本理解了如何在自己的应用中实现类似的功能。希望这些内容能帮助您在实践中更好地应用 SwiftUI,提升用户体验。