第1章:项目概述与环境搭建

第1章:项目概述与环境搭建

学习目标

  • 了解YunChangAction灵感记录应用的整体架构和功能
  • 掌握SwiftUI开发环境的配置方法
  • 创建项目基础结构并理解文件组织方式
  • 实现应用的启动屏幕和基本主题设置

理论知识讲解

灵感记录应用概述

灵感记录应用是一种专门设计用来帮助用户随时捕捉、整理和管理各种想法的工具。在日常生活和工作中,灵感往往稍纵即逝,一个好的灵感记录应用能够帮助用户快速记录这些珍贵的想法,并通过分类、标签等方式进行有效管理。

YunChangAction是一款功能丰富的灵感记录应用,它不仅提供基本的笔记功能,还集成了AI辅助分类、多种视图模式、数据导出等高级特性,帮助用户更高效地管理创意和想法。

灵感记录应用概念图

辅助功能
核心功能
记录
分类
标记
收藏
分析
推荐
生成
多种视图
多种视图
搜索
导出
导入
URL Scheme
应用快捷方式
列表视图
网格视图
搜索功能
数据导出
数据导入
快速操作
灵感笔记
笔记分类
标签系统
收藏夹
AI服务
用户

SwiftUI框架介绍

SwiftUI是Apple在2019年WWDC上推出的声明式UI框架,它彻底改变了iOS应用开发的方式。与传统的UIKit相比,SwiftUI具有以下优势:

  1. 声明式语法:使用简洁的声明式语法描述UI的外观和行为
  2. 实时预览:通过Canvas实时预览UI变化,加速开发过程
  3. 自动适配:自动支持动态类型、深色模式和各种设备尺寸
  4. 组合式设计:通过组合小型、独立的视图构建复杂界面
  5. 数据驱动:内置状态管理机制,UI会自动响应数据变化
SwiftUI
声明式UI
数据驱动
组合式设计
跨平台
简洁语法
可读性强
状态管理
@State
@Binding
@ObservedObject
@StateObject
@EnvironmentObject
视图组合
修饰符链式调用
iOS
macOS
watchOS
tvOS
布局系统
VStack
HStack
ZStack
LazyVGrid
LazyHGrid
实时预览
Canvas
Preview宏

MVVM架构模式

YunChangAction采用MVVM(Model-View-ViewModel)架构模式,这是SwiftUI应用中常用的架构模式:

  • Model(模型):表示应用的数据和业务逻辑,如InspirationNote类
  • View(视图):负责UI的展示,如ContentView、SplashScreen等
  • ViewModel(视图模型):连接Model和View,处理UI逻辑和状态管理,如InspirationManager

MVVM架构的优势在于实现了关注点分离,提高了代码的可测试性和可维护性。在SwiftUI中,通过@ObservedObject、@StateObject和@EnvironmentObject等属性包装器,可以轻松实现视图与视图模型之间的数据绑定。

表现层
逻辑层
数据层
数据
更新
绑定
用户操作
实例化
状态管理
UI组件
View
ViewModel
Model
InspirationNote
InspirationManager
ContentView/SplashScreen等

实践步骤

1. 配置开发环境

所需工具和版本
  • macOS 12.0或更高版本
  • Xcode 14.0或更高版本
  • iOS 15.0+模拟器或实机
安装步骤
  1. 从Mac App Store下载并安装最新版Xcode
    1. (如果没有安装,这里按钮会有下载字样,如果有安装按钮就是获取)
  • 安装前

  • 安装后:

在终端 配置Xcode命令行工具

在终端执行以下命令,配置Xcode command-line tools

sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch

执行sudo命令时,需要下输入macOS登录用户名的密码,且用户名具有管理员权限。
执行xcodebuild -runFirstLaunch命令时,会要求先确认Xcode license。

这里输入密码

  1. 打开Xcode并接受许可协议 ,点击Agree

  1. 安装必要的组件(模拟器、命令行工具等)

在这里插入图片描述

2. 创建新项目

  1. 打开Xcode,选择"Create a new Xcode project"
  2. 选择"App"模板,点击"Next"
  3. 填写项目信息:
    • Product Name: YunChangAction
    • Organization Identifier: com.example
    • Interface: SwiftUI
    • Language: Swift
    • 确保"Use Core Data"未选中
  4. 选择项目保存位置,点击"Create"

在这里插入图片描述

在这里插入图片描述

3. 配置项目基本信息

在这里插入图片描述

  1. 在项目导航器中选择项目文件
  2. 在"General"标签页中设置:
    • Display Name: 灵感记录
    • Deployment Info: iOS 15.0+
    • Device Orientation: Portrait
  3. 创建InfoCustom.plist文件,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>CFBundleURLTypes</key><array><dict><key>CFBundleTypeRole</key><string>Editor</string><key>CFBundleURLName</key><string>com.yunchangaction</string><key>CFBundleURLSchemes</key><array><string>yunchangaction</string></array></dict></array><key>UIApplicationShortcutItems</key><array><dict><key>UIApplicationShortcutItemIconType</key><string>UIApplicationShortcutIconTypeCompose</string><key>UIApplicationShortcutItemTitle</key><string>快速记录</string><key>UIApplicationShortcutItemType</key><string>com.yunchangaction.quicknote</string></dict></array></dict></plist>

在这里插入图片描述

4. 创建项目文件结构

为了保持代码的组织性和可维护性,我们将按照以下结构组织项目文件:

YunChangAction/
├── App/
│   ├── YunChangActionApp.swift  // 应用入口点
│   └── AppTheme.swift           // 应用主题定义
├── Views/
│   ├── SplashScreen.swift       // 启动屏幕
│   ├── ContentView.swift        // 主内容视图
│   ├── NoteViews/               // 笔记相关视图
│   └── SettingsViews/           // 设置相关视图
├── Models/
│   ├── InspirationNote.swift    // 灵感笔记模型
│   └── CategoryRecommendation.swift // AI推荐模型
├── ViewModels/
│   └── InspirationManager.swift // 灵感管理器
├── Services/
│   └── AIService.swift          // AI服务
├── Utilities/
│   └── Extensions.swift         // 扩展方法
└── Resources/
│   └── Assets.xcassets          // 资源文件

在Xcode中创建这些文件夹和文件:

  1. 在项目导航器中右键点击YunChangAction文件夹
  2. 选择"New Group"创建新文件夹
  3. 为每个文件夹创建相应的文件
    在这里插入图片描述

5. 实现应用主题

创建AppTheme.swift文件,定义应用的主题色系:

import SwiftUI// 定义应用的主题色
struct AppTheme {static let primaryColor = Color(red: 0.2, green: 0.7, blue: 0.3)static let secondaryColor = Color(red: 0.5, green: 0.8, blue: 0.5)static let accentColor = Color(red: 0.4, green: 0.8, blue: 0.7)static let backgroundColor = Color(red: 0.95, green: 0.98, blue: 0.95)
}

6. 实现启动屏幕

创建SplashScreen.swift文件,实现应用的启动屏幕:

import SwiftUI// 启动屏幕
struct SplashScreen: View {@State private var isAnimating = falsevar body: some View {ZStack {AppTheme.backgroundColor.ignoresSafeArea()VStack(spacing: 20) {Image(systemName: "lightbulb.fill").font(.system(size: 80)).foregroundColor(AppTheme.primaryColor).scaleEffect(isAnimating ? 1.2 : 1.0).animation(Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true),value: isAnimating)Text("灵感记录").font(.largeTitle).fontWeight(.bold).foregroundColor(AppTheme.primaryColor)Text("捕捉每一个闪光的想法").font(.subheadline).foregroundColor(.gray).padding(.top, 4)}}.onAppear {isAnimating = true}}
}#Preview {SplashScreen()
}

在这里插入图片描述

7. 修改应用入口点

修改YunChangActionApp.swift文件,集成启动屏幕:

import SwiftUI
import WidgetKit@main
struct YunChangActionApp: App {@StateObject private var inspirationManager = InspirationManager()@State private var isQuickNoteActive = false@Environment(\.scenePhase) private var scenePhase@State private var showSplash = truevar body: some Scene {WindowGroup {ZStack {ContentView().environmentObject(inspirationManager).preferredColorScheme(.light).accentColor(AppTheme.primaryColor).onOpenURL { url in// 处理URL Scheme,用于快速启动记录功能if url.scheme == "yunchangaction" && url.host == "quicknote" {isQuickNoteActive = true}}// 条件性显示启动屏幕if showSplash {SplashScreen().transition(.opacity).zIndex(1).onAppear {// 2秒后隐藏启动屏幕DispatchQueue.main.asyncAfter(deadline: .now() + 2) {withAnimation {showSplash = false}}}}}}}
}

8. 创建基本数据模型

创建InspirationNote.swift文件,定义灵感笔记的数据模型:

import SwiftUI// 灵感笔记模型
struct InspirationNote: Identifiable, Codable {var id = UUID()var content: Stringvar createdAt: Datevar isFavorite: Bool = falsevar category: NoteCategory = .generalvar color: NoteColor = .greenvar tags: Set<String> = []
}// 笔记分类
enum NoteCategory: String, Codable, CaseIterable, Identifiable {case general = "通用"case work = "工作"case personal = "个人"case idea = "创意"case todo = "待办"case study = "学习"case travel = "旅行"case health = "健康"var id: String { self.rawValue }var icon: String {switch self {case .general: return "doc.text"case .work: return "briefcase"case .personal: return "person"case .idea: return "lightbulb"case .todo: return "checklist"case .study: return "book"case .travel: return "airplane"case .health: return "heart"}}
}// 笔记颜色
enum NoteColor: String, Codable, CaseIterable, Identifiable {case green = "绿色"case lightGreen = "淡绿色"case mint = "薄荷色"case teal = "青色"case lime = "青柠色"var id: String { self.rawValue }var color: Color {switch self {case .green: return Color(red: 0.2, green: 0.7, blue: 0.3)case .lightGreen: return Color(red: 0.5, green: 0.8, blue: 0.5)case .mint: return Color(red: 0.4, green: 0.8, blue: 0.7)case .teal: return Color(red: 0.2, green: 0.6, blue: 0.6)case .lime: return Color(red: 0.6, green: 0.8, blue: 0.3)}}
}

代码解释

SplashScreen.swift

// @State属性包装器用于管理视图的本地状态
// 当isAnimating变化时,SwiftUI会自动重新渲染视图
@State private var isAnimating = false// ZStack用于在z轴方向叠加视图元素
ZStack {// 设置背景色并忽略安全区域,使背景色填满整个屏幕AppTheme.backgroundColor.ignoresSafeArea()// VStack用于垂直排列视图元素VStack(spacing: 20) {// 使用SF Symbols图标作为灯泡图标Image(systemName: "lightbulb.fill").font(.system(size: 80)).foregroundColor(AppTheme.primaryColor)// scaleEffect修饰符用于缩放视图// 根据isAnimating状态在1.0和1.2之间变化.scaleEffect(isAnimating ? 1.2 : 1.0)// animation修饰符定义动画效果// easeInOut表示动画曲线,duration表示动画持续时间// repeatForever使动画无限重复,autoreverses使动画来回播放.animation(Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true),value: isAnimating  // 监听这个值的变化来触发动画)// 应用标题Text("灵感记录").font(.largeTitle).fontWeight(.bold).foregroundColor(AppTheme.primaryColor)// 应用副标题Text("捕捉每一个闪光的想法").font(.subheadline).foregroundColor(.gray).padding(.top, 4)}
}
// onAppear在视图出现时执行闭包
// 这里用于启动动画
.onAppear {isAnimating = true
}

YunChangActionApp.swift

// @main标记应用的入口点
@main
struct YunChangActionApp: App {// @StateObject用于创建和管理应用级别的状态对象// inspirationManager将在整个应用生命周期内保持存在@StateObject private var inspirationManager = InspirationManager()// @State用于管理视图的本地状态@State private var isQuickNoteActive = false// @Environment用于访问环境值// scenePhase表示应用的当前状态(活跃、非活跃、后台)@Environment(\.scenePhase) private var scenePhase// 控制是否显示启动屏幕@State private var showSplash = truevar body: some Scene {WindowGroup {// ZStack用于叠加ContentView和SplashScreenZStack {ContentView()// 将inspirationManager注入环境,使其在视图层次结构中可用.environmentObject(inspirationManager)// 设置浅色模式.preferredColorScheme(.light)// 设置强调色.accentColor(AppTheme.primaryColor)// 处理URL Scheme.onOpenURL { url inif url.scheme == "yunchangaction" && url.host == "quicknote" {isQuickNoteActive = true}}// 条件性显示启动屏幕if showSplash {SplashScreen()// 设置过渡动画为淡入淡出.transition(.opacity)// 确保启动屏幕在最上层.zIndex(1).onAppear {// 延迟2秒后隐藏启动屏幕DispatchQueue.main.asyncAfter(deadline: .now() + 2) {// 使用动画效果隐藏启动屏幕withAnimation {showSplash = false}}}}}}}
}

常见问题和解决方案

1. Xcode版本兼容性问题

问题:使用较旧版本的Xcode可能无法支持最新的SwiftUI功能。

解决方案

  • 升级到最新版本的Xcode
  • 如果无法升级,可以修改代码以兼容旧版本的SwiftUI
  • 使用条件编译来处理不同版本的API差异
// 条件编译示例
#if compiler(>=5.5)
// 使用iOS 15+的API
if #available(iOS 15.0, *) {Text("新API").listRowSeparator(.hidden)
} else {// 兼容iOS 14及更早版本Text("旧API")
}
#else
// 兼容旧版本Swift编译器
Text("旧API")
#endif

2. 预览功能不工作

问题:SwiftUI预览有时会停止工作或显示错误。

解决方案

  • 重启Xcode预览(点击预览窗口中的刷新按钮)
  • 确保预览代码正确(检查#Preview宏的使用)
  • 清理项目(Product > Clean Build Folder)
  • 重启Xcode
  • 检查是否有编译错误

3. 环境对象注入问题

问题:在视图中无法访问通过environmentObject注入的对象。

解决方案

  • 确保在视图层次结构的顶层正确注入了环境对象
  • 检查是否正确使用了@EnvironmentObject属性包装器
  • 确保环境对象类型匹配
// 正确注入环境对象
ContentView().environmentObject(inspirationManager)// 在子视图中正确访问环境对象
struct ChildView: View {@EnvironmentObject var inspirationManager: InspirationManagervar body: some View {Text("共有\(inspirationManager.notes.count)条笔记")}
}

4. 启动屏幕闪烁问题

问题:启动屏幕可能会在显示后立即消失或闪烁。

解决方案

  • 确保延迟足够长的时间再隐藏启动屏幕
  • 使用withAnimation包装状态变化,使过渡更平滑
  • 添加适当的过渡动画
// 平滑过渡的示例
.onAppear {// 立即开始动画isAnimating = true// 延迟2秒后隐藏启动屏幕DispatchQueue.main.asyncAfter(deadline: .now() + 2) {withAnimation(.easeOut(duration: 0.5)) {showSplash = false}}
}

本章小结

在本章中,我们完成了YunChangAction灵感记录应用的基础搭建工作:

  1. 了解了灵感记录应用的概念和YunChangAction的核心功能
  2. 学习了SwiftUI框架的基本概念和MVVM架构模式
  3. 配置了开发环境并创建了项目
  4. 设计了合理的项目文件结构
  5. 实现了应用的主题设置和启动屏幕
  6. 创建了基本的数据模型

这些工作为后续开发各个功能模块奠定了坚实的基础。在接下来的章节中,我们将逐步实现灵感记录、AI辅助分类、多视图模式等核心功能。

课后练习

  1. 修改主题色系:尝试修改AppTheme.swift文件中的颜色定义,创建自己喜欢的配色方案,并观察应用外观的变化。
  2. 增强启动屏幕:为SplashScreen添加更多动画效果,如淡入淡出、旋转或波浪效果,使启动体验更加生动。
  3. 扩展数据模型:为InspirationNote模型添加新的属性,如优先级、提醒时间或位置信息,并思考这些属性如何影响应用的功能。
  4. 实现深色模式:修改YunChangActionApp.swift,使应用支持自动切换深色模式,并为深色模式定义适当的颜色方案。
  5. 研究SwiftUI生命周期:探索@Environment(.scenePhase)的用法,实现当应用进入后台时自动保存数据的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.3.3总结

周一这天&#xff0c;我约了绩效教练&#xff0c;主要想了解专业类绩效的考核方式以及想知道如何拿到一个更好的绩效。其他的岗位并不是很清楚&#xff0c;但是专业类的岗位&#xff0c;目前采取绝对考核&#xff0c;管理层和专家岗采取相对考核&#xff0c;有末尾淘汰。 通过…

FastGPT 源码:基于 LLM 实现 Rerank (含Prompt)

文章目录 基于 LLM 实现 Rerank函数定义预期输出实现说明使用建议完整 Prompt 基于 LLM 实现 Rerank 下边通过设计 Prompt 让 LLM 实现重排序的功能。 函数定义 class LLMReranker:def __init__(self, llm_client):self.llm llm_clientdef rerank(self, query: str, docume…

LeetCode 1745.分割回文串 IV:动态规划(用III或II能直接秒)

【LetMeFly】1745.分割回文串 IV&#xff1a;动态规划&#xff08;用III或II能直接秒&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/palindrome-partitioning-iv/ 给你一个字符串 s &#xff0c;如果可以将它分割成三个 非空 回文子字符串&#xff0c;…

25年3月5日

1.思维导图 2.不太会 #include "head.h" int main(int argc, const char *argv[]) {int fdopen("../xiaoxin.bmp","O_RDONLY");if(fd-1)printf("open error");//大小struct stat st;if(stat("…

全球首创!微软发布医疗AI助手,终结手写病历时代

今天凌晨&#xff0c;微软发布了医疗界首个用于临床工作流程的AI助手Microsoft Dragon Copilot。 Dragon Copilot是基于语音文本的混合架构&#xff0c;能够将医生的语音或临床口述内容实时转换为文本。例如&#xff0c;医生可以通过语音输入患者的病历信息、医嘱或诊断结果&a…

[自动驾驶-传感器融合] 多激光雷达的外参标定

文章目录 引言外参标定原理ICP匹配示例参考文献 引言 多激光雷达系统通常用于自动驾驶或机器人&#xff0c;每个雷达的位置和姿态不同&#xff0c;需要将它们的数据统一到同一个坐标系下。多激光雷达外参标定的核心目标是通过计算不同雷达坐标系之间的刚性变换关系&#xff08…

Blazor-路由模板(下)

路由约束 类型约束 我们这里使用{id:int}限制路由&#xff0c;id为int类型&#xff0c;并且路由参数 id 对应的 Id 属性也必须是 int 类型。我们试试能否正常访问 page "/demoPage/{id:int}" <h3>demoPage</h3> <h2>路由参数Id&#xff1a;Id&l…

多线程-JUC源码

简介 JUC的核心是AQS&#xff0c;大部分锁都是基于AQS扩展出来的&#xff0c;这里先结合可重入锁和AQS&#xff0c;做一个讲解&#xff0c;其它的锁的实现方式也几乎类似 ReentrantLock和AQS AQS的基本结构 AQS&#xff0c;AbstractQueuedSynchronizer&#xff0c;抽象队列…

通过多线程获取RV1126的AAC码流

目录 一RV1126多线程获取音频编码AAC码流的流程 1.1AI模块的初始化并使能 1.2AENC模块的初始化 ​​​​​​​1.3绑定AI模块和AENC模块 ​​​​​​​1.4多线程获取每一帧AAC码流 ​​​​​​​1.5每个AAC码流添加ADTSHeader头部 ​​​​​​​1.6写入具体每一帧AAC的…

JVM常用概念之对象初始化的成本

在JVM常用概念之新对象实例化博客中我讲到了对象的实例化&#xff0c;主要包含分配&#xff08;TLAB&#xff09;、系统初始化、用户初始化&#xff0c;而我在JVM常用概念之线程本地分配缓冲区&#xff08;ThreadLocal Allocation Buffer&#xff0c;TLAB&#xff09;博客中也讲…

java后端开发day27--常用API(二)正则表达式爬虫

&#xff08;以下内容全部来自上述课程&#xff09; 1.正则表达式&#xff08;regex&#xff09; 可以校验字符串是否满足一定的规则&#xff0c;并用来校验数据格式的合法性。 1.作用 校验字符串是否满足规则在一段文本中查找满足要求的内容 2.内容定义 ps&#xff1a;一…

AI---DevOps常备工具(‌AI-Integrated DevOps Essential Tools)

AI---DevOps常备工具 技术领域正在迅速发展&#xff0c;随着我们步入 2025 年&#xff0c;有一点是明确的&#xff1a;人工智能&#xff08;AI&#xff09;不再只是一个流行词&#xff0c;它是每个 DevOps 工程师都需要掌握的工具。随着云环境的复杂性增加、对更快部署的需求以…

Pytorch中的主要函数

目录 一、torch.manual_seed(seed)二、torch.cuda.manual_seed(seed)三、torch.rand(*size, outNone, dtypeNone, layouttorch.strided, deviceNone, requires_gradFalse)四、给大家写一个常用的自动选择电脑cuda 或者cpu 的小技巧五、torch.version.cuda&#xff1b;torch.bac…

Spring Boot中对接Twilio以实现发送验证码和验证短信码

Twilio介绍 Twilio是一家提供云通信服务的公司&#xff0c;旨在帮助开发者和企业通过简单的API实现各种通信功能。以下是Twilio的一些主要特点和服务介绍&#xff1a; 核心功能 短信服务&#xff08;SMS&#xff09;&#xff1a;允许用户通过API发送和接收短信&#xff0c;支…

VSCode详细安装步骤,适用于 Windows/macOS/Linux 系统

以下是 Visual Studio Code (VSCode) 的详细安装步骤&#xff0c;适用于 Windows/macOS/Linux 系统&#xff1a; VSCode 的详细安装步骤 一、Windows 系统安装1. 下载安装包2. 运行安装程序3. 验证安装 二、macOS 系统安装1. 方法一&#xff1a;官网下载安装包2. 方法二&#x…

基于PyTorch的深度学习3——基于autograd的反向传播

反向传播&#xff0c;可以理解为函数关系的反向传播。

设备管理系统功能与.NET+VUE(IVIEW)技术实现

在现代工业和商业环境中&#xff0c;设备管理系统&#xff08;Equipment Management System&#xff0c;简称EMS&#xff09;是确保设备高效运行和维护的关键工具。本文采用多租户设计的设备管理系统&#xff0c;基于.NET后端和VUE前端&#xff08;使用IVIEW UI框架&#xff09…

PHP之特性

在你有别的编程语言的基础下&#xff0c;你想学习PHP&#xff0c;可能要了解的PHP特有的东西。 定界符 使用<<<TT(可以是任意字符&#xff0c;但是不可以在别的地方使用过)和TT&#xff0c;会解析html格式和变量&#xff0c;如果在<<<后面加上单引号就会不…

9-Agent大模型中工作流的使用方法分析

目录 关键词 摘要 速览 配置插件进行新闻内容查找的工作流设置 自动化调用用户输入变量的插件配置教程 配置大模型以整理并简要输出新闻内容 新闻内容总结功能调试与优化 搭建与发布工作流优化布局的流程详解 创建和配置智能体工作流程 调试页面与工作流配置演示 思…

记一次:泛微OA集成Mybatis后 insert/update执行成功,但未真正插入或修改数据

背景&#xff1a;通过Mybatis插入数据或更新数据&#xff0c;显示插入/更新成功&#xff0c;查询数据库&#xff0c;发现并未插入成功、数据也没更新成功。下面是Mapper文件 public interface TestOrmMapper {int insertByTest(Param("requestId") Integer requestI…