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"))