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 小时前
python学习——核心语法三
java·python·学习
Afans_fire2 小时前
多渠道广告归因:3种逻辑解决效果分配难题
笔记·内容运营·广告投放·广告营销·徐州巨量星河
泉飒2 小时前
qt软件无法打开编译
笔记·工业视觉
七老板的blog2 小时前
从持久化任务到多 Agent 协作
python·学习·ai
book01212 小时前
华为ensp学习日志 记2026
学习·华为·智能路由器
Huangxy__3 小时前
线程池的学习
学习
小丶舟3 小时前
6GB显卡跑Hermes Agent!开源AI自学习编程Agent实测
人工智能·学习·开源
穗余3 小时前
2026 AI x Web3 School共学营笔记-Day10-Women Builders in AI × Web3
人工智能·笔记·web3
Bechamz3 小时前
大数据开发学习Day45
大数据·学习