Swift学习笔记34-MVC架构,SwiftUI与UIkit混编练习

Model可以分为三种:

1.存档数据的传输Model

2.网络请求,请求到的数据的Model

3.从数据库拿到的Model·1

MVC的Model

4.页面Model:用于标记页面渲染的元素,是由前三个model生成来的。

一个页面一个Model,除非只有一个元素不需要用结构体包裹;
可以把共有的部分弄在Base里,然后和他有关的子类直接继承它。

如果一个Model里大多数内容都不需要的话,就不要传进去。

只作为Model中static函数里的参数,到时候再把1.2.3类型的Model传进去就好了,这样就可以避免把一整个超大Model传来传去。

一些固定的东西,比如颜色,可以存在一个固定的页面,而共用的东西,应该写在Public里。

网络请求到的Model

swift 复制代码
//
//  SImpleReportModel.swift
//  RequestPratice_0525
//
//  Created by sakiko on 2026/5/25.
//

struct SimpleReportModel {
    var advantage: String
    var career: String
    var celebritys: String
    var disadvantage: String
    var id: Int
    var pairing: String
    var result_str: String
    
    //根据传入的字典中的键来取键值,再将其传入Model
    static func base(with dic:[String: Any]) -> SimpleReportModel {
        let advantage: String = dic["advantage"] as? String ?? ""
        let career: String = dic["career"] as? String ?? ""
        let celebritys: String = dic["celebritys"] as? String ?? ""
        let disadvantage: String = dic["disadvantage"] as? String ?? ""
        let id: Int = dic["id"] as? Int ?? 0
        let pairing: String = dic["pairing"] as? String ?? ""
        let result_str: String = dic["result_str"] as? String ?? ""
        
        return SimpleReportModel(advantage: advantage, career: career, celebritys: celebritys, disadvantage: disadvantage, id: id, pairing: pairing, result_str: result_str)
    }
    
    static func empty() -> SimpleReportModel {
        return SimpleReportModel(advantage: "", career: "", celebritys: "", disadvantage: "", id: 0, pairing: "", result_str: "")
    }
}

用于存放渲染UI元素的Model

swift 复制代码
struct DichoBase {
    var i: Int
    var e: Int
    var n: Int
    var s: Int
    var f: Int
    var t: Int
    var p: Int
    var j: Int
    var colors: [String] =  ["yellow_eightFuncBg", "green_eightFuncBg", "blue_eightFuncBg", "purple_eightFuncBg"]
    var mbtiColor: String
    
    static func base(with eightBase:EightFuncBase) -> DichoBase {
        print(eightBase)
        let e = eightBase.fe_value + eightBase.te_value + eightBase.ne_value + eightBase.se_value
        let i = eightBase.fi_value + eightBase.ti_value + eightBase.si_value + eightBase.ni_value
        let n = eightBase.ni_value + eightBase.ne_value
        let s = eightBase.si_value + eightBase.se_value
        let f = eightBase.fe_value + eightBase.fi_value
        let t = eightBase.ti_value + eightBase.te_value
        let p = eightBase.si_value + eightBase.se_value + eightBase.ni_value + eightBase.ne_value
        let j = eightBase.fe_value + eightBase.fi_value + eightBase.ti_value + eightBase.te_value
        let colors = ReportColors.getColors(with: eightBase.result_str)
        return DichoBase(i: i, e: e, n: n, s: s, f: f, t: t, p: p, j: j, mbtiColor: colors)
    }
}
MVC的ViewController

一个ViewController必有一个View,这个View新开一页写,通常是用SwiftUI写,然后再创建这个View的实例将其扩展到全屏显示。

MVC的View

这里就是真正写UI的地方,是UI层,用的SwiftUI,需要变的地方就用对应的Model中的变量表示。

一个大View来套ScrollView, 传数据Model进来,再把数据Model传进需要的Cell里,逐个打印。

整页的View:也就是ViewController的View

swift 复制代码
struct ReportView: View {
    var model: SimpleReportModel
    var eightFuncBase: EightFuncBase
    var body: some View {
        ZStack{
                        ReportMainCell(reportMainBase: ReportMainBase(eightBase: eightFuncBase, bg_img: "result_img_\(ReportColors.getColors(with: model.result_str))bg"))
        ScrollView(.vertical, showsIndicators: false) {
            

                //result_img_\(ReportColors.getColors(with: m.result_str))bg
                VStack {
                    ReportViewTitleCell(reportViewTitileModel: ReportViewTitleModel.getBgColor(with: model.result_str))
                    Spacer()
                    EightFuncMoCell(eightFuncMoModel: EightFuncMoModel.getColor(with: eightFuncBase))
                    Spacer()
                    DichoCell(dichoBase: DichoBase.base(with: eightFuncBase))
                    Spacer()
                    EightFuncOrderCell(eightFuncOrderModel: EightFuncOrderModel.getEightFuncsOrder(with: model.result_str))
                    Spacer()
                    AdvantageCell(advantageModel: AdvantageModel.getAdvantage(with: model))
                    Spacer()
                    DisadvantageCell(disadvantageModel: DisadvantageModel.getAdvantage(with: model))
                    Spacer()
                    CareerCell(careerModel: CareerModel.getCareerStr(with: model))
                    Spacer()
                    PairCell(pairModel: PairModel.get_names_details(with: model.result_str))
                    Spacer()
                    CelebritiesCell(celebritiesModel: CelebritiesModel.getImgs(with: model))
                }
            }
        }
    }
}

Cell,也就是单独部分的View

swift 复制代码
//
//  CelebritiesCell.swift
//  RequestPratice_0525
//
//  Created by sakiko on 2026/5/29.
//

import SwiftUI
struct CelebritiesCell: View {
    var celebritiesModel: CelebritiesModel
//    var eightFuncBase: EightFuncBase
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 20)
                .foregroundColor(.white)
                .frame(width: SCREENWIDTH - 32)
            VStack {
                HStack {
                    Image("result_img_cele_\(celebritiesModel.color)titlebg")
                        .resizable()
                        .frame(width: 175, height: 42)
                        .offset(x: 16 + 16)
                    Spacer()
                    
                }
                .padding(.top, 16)
                VStack { //头像与名字
                    
                    ForEach((0..<celebritiesModel.celeHeadImg.count), id: \.self) { idx in
                        let celeName = celebritiesModel.celeHeadImg[idx]
                        let celeName_str = NSLocalizedString(celeName, comment: "")
                        let celeName_front = CelebritiesModel.clipCeleName_front(with: celeName_str)
                        let celeName_behind = CelebritiesModel.cilpCeleName_behind(with: celeName_str)
                        
                        HStack {
                            
                            Image(celeName)
                                .resizable()
                                .frame(width: 32, height: 32)
                                .cornerRadius(16)
                                .offset(x: 32)
                            
                            VStack(alignment: .leading) {
                                Text(celeName_front)
                                    .font(.system(size: 14))
                                    .foregroundColor(.black)
                                
                                Text(celeName_behind)
                                    .font(.system(size: 12))
                                    .foregroundColor(.gray)
                                    .offset(y: 2)
                            }
                            .offset(x: 32)
                            .frame(maxWidth: .infinity, alignment: .leading)
                        Spacer()
                        }
                        .padding(.bottom, 8)
                        
                        
                        Text(CelebritiesModel.getDetailIntros(with: celeName))
                            .font(.system(size: 14))
                            .foregroundColor(.black)
                            .frame(width: SCREENWIDTH - 32 - 32)
                            .lineSpacing(4)
                            .padding(.bottom, 24)
//                        Spacer()
                    }
                }
                
            }
        }
    }
}

其他:

Text(advantageModel.advantage.replacingOccurrences(of: "-", with: "\n"))

批量更改请求到的文件换行符

矩形切圆角,矩形设置背景渐变。

swift 复制代码
RoundedRectangle(cornerRadius: 10)
                    .frame(width: CGFloat((Double(funcNum) / 90) * CGFloat(SCREENWIDTH - ((16 + 18) * 2))) , height: 12)
                    .background (
                        LinearGradient(
                            colors: [Color(eightFuncColor).opacity(0.2),
                                      Color(eightFuncColor)],
                            startPoint: .leading, endPoint: .trailing
                        )
                    )
                    .foregroundColor(.clear)
                    .clipShape(RoundedRectangle(cornerRadius: 10))

拆分从网络上请求下来的字符串,遍历全部元素,并将其存放在数组中

swift 复制代码
let sub_career = String(m.career).split(separator: "、").map(String.init)
                print(sub_career)

SwiftUI使用数组遍历数组中的元素,实现打印多个组件的效果。

swift 复制代码
VStack {
                    ForEach((0..<careerModel.career_str_arr.count), id: \.self) {
                        idx in
                        ZStack {
                            RoundedRectangle(cornerRadius: 16)
                                .frame(height: 22)
                                .foregroundColor(Color(career_colorSet[idx]))
                            Text("\(careerModel.career_str_arr[idx])")
                                .font(.system(size: 14))
                                .foregroundColor(.black)
                        }

                    }

SwiftUI图片旋转(默认围绕中心旋转)

2D 平面旋转:.rotationEffect()

这是最常用的 API,让图片围绕某一个中心点在屏幕平面内旋转。

swift 复制代码
Image("your_image_name")
    .resizable()
    .frame(width: 100, height: 100)
    .rotationEffect(.degrees(45)) // 🔄 顺时针旋转 45 度

SwiftUI的text对齐方式

.multilineTextAlignment(.center)

SwiftUI让VStack里的内容绝对靠左, 加在最下面

.frame(maxWidth: .infinity, alignment: .leading)

swift 复制代码
VStack(alignment: .leading) {
                                Text(celeName_front)
                                    .font(.system(size: 14))
                                    .foregroundColor(.black)
//                                    .offset(x: 8)
                                
                                Text(celeName_behind)
                                    .font(.system(size: 12))
                                    .foregroundColor(.gray)
//                                    .offset(x: 4)
                            }
                            .offset(x: 32)
                            .frame(maxWidth: .infinity, alignment: .leading)

Swift中除法是默认整除,小数除法要加Double或者CGFloat。要根据比例去表示的话,必须得加,否则很有可能得出的数被舍为0

swift 复制代码
RoundedRectangle(cornerRadius: 10)
                            .frame(width: CGFloat(Double(dichoBase.s) / 180) * 120 ,height: 12)
                            .foregroundColor(Color("green_eightFunc"))
相关推荐
通信小呆呆2 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
H__Rick2 天前
自动对焦学习-3
人工智能·学习·计算机视觉
Daisy Lee2 天前
量化学习-第1章-什么是量化金融
学习·金融·datawhale
Alsn862 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
YM52e2 天前
买菜计算器小应用 - HarmonyOS ArkUI 开发实战-PC版本
学习·华为·harmonyos·鸿蒙·鸿蒙系统
小雨下雨的雨2 天前
HarmonyOS ArkUI训练营入门-组件掌握系列-Animation 动画效果实现-PC版本
学习·华为·harmonyos·鸿蒙
闪闪发亮的小星星2 天前
高斯光以及高斯光公式解释
笔记
cqbzcsq3 天前
CellFlow虚拟细胞论文阅读
论文阅读·人工智能·笔记·学习·生物信息
YangYang9YangYan3 天前
2026初入职场学习数据分析的价值
学习·数据挖掘·数据分析
阿米亚波3 天前
【Windows】QEMU 启动 openEuler aarch64/arm64 架构系统 + 离线软件源
linux·windows·经验分享·笔记·架构·arm