
灵感记录应用是一种专门设计用来帮助用户随时捕捉、整理和管理各种想法的工具。在日常生活和工作中,灵感往往稍纵即逝,一个好的灵感记录应用能够帮助用户快速记录这些珍贵的想法,并通过分类、标签等方式进行有效管理。
YunChangAction是一款功能丰富的灵感记录应用,它不仅提供基本的笔记功能,还集成了AI辅助分类、多种视图模式、数据导出等高级特性,帮助用户更高效地管理创意和想法。
灵感记录应用概念图
辅助功能
核心功能
记录
分类
标记
收藏
分析
推荐
生成
多种视图
多种视图
搜索
导出
导入
URL Scheme
应用快捷方式
列表视图
网格视图
搜索功能
数据导出
数据导入
快速操作
灵感笔记
笔记分类
标签系统
收藏夹
AI服务
用户
SwiftUI是Apple在2019年WWDC上推出的声明式UI框架,它彻底改变了iOS应用开发的方式。与传统的UIKit相比,SwiftUI具有以下优势:
SwiftUI
声明式UI
数据驱动
组合式设计
跨平台
简洁语法
可读性强
状态管理
@State
@Binding
@ObservedObject
@StateObject
@EnvironmentObject
视图组合
修饰符链式调用
iOS
macOS
watchOS
tvOS
布局系统
VStack
HStack
ZStack
LazyVGrid
LazyHGrid
实时预览
Canvas
Preview宏
YunChangAction采用MVVM(Model-View-ViewModel)架构模式,这是SwiftUI应用中常用的架构模式:
MVVM架构的优势在于实现了关注点分离,提高了代码的可测试性和可维护性。在SwiftUI中,通过@ObservedObject、@StateObject和@EnvironmentObject等属性包装器,可以轻松实现视图与视图模型之间的数据绑定。
表现层
逻辑层
数据层
数据
更新
绑定
用户操作
实例化
状态管理
UI组件
View
ViewModel
Model
InspirationNote
InspirationManager
ContentView/SplashScreen等


在终端 配置Xcode命令行工具
在终端执行以下命令,配置Xcode command-line tools
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
执行sudo命令时,需要下输入macOS登录用户名的密码,且用户名具有管理员权限。
执行xcodebuild -runFirstLaunch命令时,会要求先确认Xcode license。

这里输入密码





<?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>

为了保持代码的组织性和可维护性,我们将按照以下结构组织项目文件:
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中创建这些文件夹和文件:
在项目导航器中右键点击YunChangAction文件夹
选择"New Group"创建新文件夹
为每个文件夹创建相应的文件

创建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)
}
创建SplashScreen.swift文件,实现应用的启动屏幕:
import SwiftUI
// 启动屏幕
struct SplashScreen: View {
@State private var isAnimating = false
var 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()
}

修改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 = true
var 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
}
}
}
}
}
}
}
}
创建InspirationNote.swift文件,定义灵感笔记的数据模型:
import SwiftUI
// 灵感笔记模型
struct InspirationNote: Identifiable, Codable {
var id = UUID()
var content: String
var createdAt: Date
var isFavorite: Bool = false
var category: NoteCategory = .general
var color: NoteColor = .green
var 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)
}
}
}
// @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
}
// @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 = true
var body: some Scene {
WindowGroup {
// ZStack用于叠加ContentView和SplashScreen
ZStack {
ContentView()
// 将inspirationManager注入环境,使其在视图层次结构中可用
.environmentObject(inspirationManager)
// 设置浅色模式
.preferredColorScheme(.light)
// 设置强调色
.accentColor(AppTheme.primaryColor)
// 处理URL Scheme
.onOpenURL { url in
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
}
}
}
}
}
}
}
}
问题 :使用较旧版本的Xcode可能无法支持最新的SwiftUI功能。
解决方案 :
// 条件编译示例
#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
问题 :SwiftUI预览有时会停止工作或显示错误。
解决方案 :
问题 :在视图中无法访问通过environmentObject注入的对象。
解决方案 :
// 正确注入环境对象
ContentView()
.environmentObject(inspirationManager)
// 在子视图中正确访问环境对象
struct ChildView: View {
@EnvironmentObject var inspirationManager: InspirationManager
var body: some View {
Text("共有\(inspirationManager.notes.count)条笔记")
}
}
问题 :启动屏幕可能会在显示后立即消失或闪烁。
解决方案 :
// 平滑过渡的示例
.onAppear {
// 立即开始动画
isAnimating = true
// 延迟2秒后隐藏启动屏幕
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation(.easeOut(duration: 0.5)) {
showSplash = false
}
}
}
在本章中,我们完成了YunChangAction灵感记录应用的基础搭建工作:
这些工作为后续开发各个功能模块奠定了坚实的基础。在接下来的章节中,我们将逐步实现灵感记录、AI辅助分类、多视图模式等核心功能。
