Generics/泛型, ViewBuilder/视图构造器 的使用

1. Generics 泛型的定义及使用

1.1 创建使用泛型的实例 GenericsBootcamp.swift

Swift 复制代码
import SwiftUI

struct StringModel {
    let info: String?
    func removeInfo() -> StringModel{
        StringModel(info: nil)
    }
}

struct BoolModel {
    let info: Bool?
    func removeInfo() -> BoolModel{
        BoolModel(info: nil)
    }
}

// CustomType = T
struct GenericModel<T>{
    let info: T?
    func removeInfo() -> GenericModel{
        GenericModel(info: nil)
    }
}

class GenericsViewModel: ObservableObject{
    /// 定义具体类型
    @Published var stringModel = StringModel(info: "hello, word!")
    @Published var boolModel = BoolModel(info: true)
    
    /// 定义泛型
    @Published var genericStringModel = GenericModel(info: "Hello, world!")
    @Published var genericBoolModel = GenericModel(info: true)
    
    func removeData(){
        stringModel = stringModel.removeInfo()
        boolModel = boolModel.removeInfo()
        genericStringModel = genericStringModel.removeInfo()
        genericBoolModel = genericBoolModel.removeInfo()
    }
}

/// 泛型 View
struct GenericView<T: View>: View{
    let content: T
    let title: String
    
    var body: some View{
        VStack {
            Text(title)
            content
        }
    }
}

/// 泛型
struct GenericsBootcamp: View {
    @StateObject private var viewModel: GenericsViewModel
    
    init() {
        _viewModel = StateObject(wrappedValue: GenericsViewModel())
    }
    
    var body: some View {
        VStack {
            GenericView(content: Text("custom content"), title: "new View")
            Text(viewModel.stringModel.info ?? "No data")
            Text(viewModel.boolModel.info?.description ?? "No data")
            
            Text(viewModel.genericStringModel.info ?? "No data")
            Text(viewModel.genericBoolModel.info?.description ?? "No data")
        }.onTapGesture {
            viewModel.removeData()
        }
    }
}

struct GenericsBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        GenericsBootcamp()
    }
}

1.2 效果图:

2. ViewBuilder 视图构造器的定义及使用

2.1 创建视图构造器的实例 ViewBuilderBootcamp.swift

Swift 复制代码
import SwiftUI

/// 常规标题视图
struct HeaderViewRegular: View{
    let title: String
    let description: String?
    let iconName: String?
    
    var body: some View{
        VStack(alignment: .leading) {
            Text(title)
                .font(.largeTitle)
                .fontWeight(.semibold)
            
            if let description = description{
                Text(description)
                    .font(.callout)
            }
            
            if let iconName = iconName{
                Image(systemName: iconName)
            }
            
            RoundedRectangle(cornerRadius: 5)
                .frame(height: 2)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
    }
}
/// 通用的标题视图
struct HeaderViewGeneric<Content: View>: View {
    let title: String
    // 泛型,可以为任何类型
    let content: Content
    
    init(title: String, @ViewBuilder content: () -> Content) {
        self.title = title
        self.content = content()
    }
    
    var body: some View{
        VStack(alignment: .leading) {
            Text(title)
                .font(.largeTitle)
                .fontWeight(.semibold)
            
            content
            
            RoundedRectangle(cornerRadius: 5)
                .frame(height: 2)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
    }
}

/// 自定义水平堆栈视图
struct CustomHStack<Content: View>:View{
    let content: Content
    
    init(@ViewBuilder content: () -> Content){
        self.content = content()
    }
    
    var body: some View{
        HStack {
            content
        }
    }
}

/// 视图构造器
struct ViewBuilderBootcamp: View {
    var body: some View {
        VStack {
            HeaderViewRegular(title: "New Title", description: "Hello", iconName: "heart.fill")
            HeaderViewRegular(title: "Another title", description: nil, iconName: nil)
            HeaderViewGeneric(title: "Generic 3") {
                VStack {
                    Text("Hello, world!")
                    Image(systemName: "bolt.fill")
                }
            }
            
            CustomHStack {
                Text("Hi")
                Text("Wo")
            }
            
            HStack {
                Text("Hi")
                Text("Wo")
            }
            Spacer()
        }
    }
}

/// 本地视图构造器
struct LocalViewBuilder: View{
    
    enum ViewType {
        case one, two, three
    }
    
    let type: ViewType
    
    /// 视图构造器
    var body: some View {
        VStack {
            headerSection
        }
    }
    
    /// 标题部分 头部分
    @ViewBuilder private var headerSection: some View{
        switch type {
        case .one:
            oneView
        case .two:
            twoView
        case .three:
            threeView
        }
    }
    
    /// 视图一
    @ViewBuilder private var oneView: some View{
        Text("One!")
    }
    
    /// 视图二
    private var twoView: some View{
        VStack {
            Text("Two 2")
            Image(systemName: "heart.fill")
        }
    }
    
    /// 视图三
    private var threeView: some View{
        Image(systemName: "heart.fill")
    }
}

struct ViewBuilderBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        //ViewBuilderBootcamp()
        LocalViewBuilder(type: .one)
    }
}

2.2 效果图:

相关推荐
ZC跨境爬虫15 小时前
跟着 MDN 学 HTML day_18:(HTML 表格进阶特性与无障碍——从标题结构到屏幕阅读器适配)
前端·笔记·ui·html·音视频
苍煜16 小时前
SkyWalking最新实操入门博客:微服务可观测性搭建+原理详解+从零部署+UI使用教程
ui·微服务·skywalking
人月神话-Lee16 小时前
两个改动,让这个iOS OCR SDK识别成功率翻了一倍
ios·ocr·ai编程·身份证识别·银行卡识别
东坡肘子16 小时前
让 AI 从称手到称心 -- 肘子的 Swift 周报 #134
人工智能·swiftui·swift
ZC跨境爬虫16 小时前
跟着 MDN 学 HTML day_16:(音频与视频处理——从画布滤镜到3D沉浸音频的进阶指南)
前端·javascript·ui·3d·html·音视频
sweet丶1 天前
流程图解:Asset Catalog 的完整生命周期
ios
ZC跨境爬虫1 天前
跟着 MDN 学 HTML day_15:(媒体缓冲、拖动与时间范围控制)
前端·笔记·ui·html·edge浏览器·媒体
ZC跨境爬虫2 天前
Python Django开发者转向微信小程序:从架构理解到第一行代码的完整准备指南
开发语言·python·ui·微信小程序·django
ZC跨境爬虫2 天前
跟着 MDN 学 HTML day_13:多媒体嵌入 —— 视频与音频
前端·css·笔记·ui·html·音视频
sakiko_2 天前
UIKit学习笔记3-布局、滚动视图、隐藏或显示视图
前端·笔记·学习·objective-c·swift·uikit