AI 辅助编程实战:从零到一开发 Swift 性能框架的经验分享 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Taoist
V2EX    iOS

AI 辅助编程实战:从零到一开发 Swift 性能框架的经验分享

  •  
  •   Taoist 107 天前 1417 次点击
    这是一个创建于 107 天前的主题,其中的信息可能已经有所发展或是发生改变。

    [实验] 此文章由 Cursor 根据项目翻阅项目代码和文档后, 加上本人的一些信息输入自动生成, 我只改了几处明显的错误, 每处不超过一行

    前言

    作为一名 iOS 开发者,我一直被两个问题困扰:重复的网络请求浪费资源,缓存策略难以精确控制。最近两个月,我决定用 AI 辅助编程的方式来彻底解决这些问题,最终开发出了一个名为Monsra的 Swift 性能框架。

    整个过程让我重新思考了"编程"这个概念,也让我对 AI 协作开发有了全新的认识。今天想分享一下这次 AI 辅助开发的完整经历,包括遇到的坑、解决方案,以及一些意外的收获。

    项目背景:那些让人头疼的性能问题

    问题一:重复网络请求的噩梦

    相信很多 iOS 开发者都遇到过这种情况:

    // 场景:多个 ViewController 同时需要用户数据 class UserProfileViewController { func viewDidLoad() { API.fetchUserProfile { result in // 处理结果 } } } class SettingsViewController { func viewDidLoad() { API.fetchUserProfile { result in // 重复请求! // 处理结果 } } } class NotificationViewController { func viewDidLoad() { API.fetchUserProfile { result in // 又一个重复请求! // 处理结果 } } } 

    结果:3 个页面同时加载,发出 3 个完全相同的网络请求。浪费流量,增加服务器负担,用户体验还差。

    问题二:缓存策略的复杂性

    iOS 开发中的缓存问题同样让人头疼:

    • NSCache: 功能简单,无法精确控制过期时间
    • 自己实现: 要考虑内存限制、过期策略、线程安全等一堆问题
    • 第三方库: 要么功能不全,要么太重太复杂

    决定:用 AI 协作解决这些问题

    面对这些痛点,我决定开发一个专门的框架来彻底解决这些问题。但这次,我想尝试一种全新的开发模式:AI 辅助编程。

    AI 协作开发的分工策略

    经过思考,我制定了一个明确的分工策略:

    我负责的部分(核心创造)

    • 架构设计:整体框架结构,模块划分
    • 核心算法:执行合并逻辑,缓存淘汰策略
    • 业务逻辑:具体的 API 设计和实现
    • 示例代码:真实场景的使用案例

    AI 负责的部分(辅助优化)

    • 单元测试:各种边界情况和异常场景
    • 代码审查:代码质量,最佳实践建议
    • 文档编写:API 文档,README ,使用指南
    • 工程配置:CI/CD ,GitHub Actions ,项目配置
    • 代码规范:注释补全,格式化,命名优化

    这样分工的好处是:我专注于最需要创造性思维的部分,AI 帮我处理那些重复性、规范性的工作。

    框架设计:两大核心组件

    基于对问题的分析,我设计了两个核心组件:

    1. TaskManager:智能任务执行管理器

    MonoTask - 单任务执行合并

    // 创建一个处理用户资料获取的任务 let userProfileTask = MonoTask<UserProfile>( resultExpireDuration: 300.0 // 5 分钟缓存 ) { callback in // 实际的网络请求逻辑 API.fetchUserProfile { result in callback(result) } } // 多个地方同时调用,只会执行一次网络请求 Task { let profile1 = await userProfileTask.asyncExecute() // 发起网络请求 let profile2 = await userProfileTask.asyncExecute() // 返回缓存结果 let profile3 = await userProfileTask.asyncExecute() // 返回缓存结果 } 

    KVLightTasksManager - 轻量级批处理

    // 批量获取用户帖子,自动合并重复 ID let postManager = KVLightTasksManager<String, Post>( config: .init( dataProvider: .asyncMultiprovide(maximumBatchCount: 10) { postIDs in return try await API.fetchPosts(ids: postIDs) } ) ) // 三个 ViewModel 请求重叠的帖子 ID ,自动批处理 postManager.fetch(keys: ["101", "102", "103"]) { id, result in // 处理单个帖子结果 } 

    KVHeavyTasksManager - 重型任务管理

    // 大文件下载,支持进度跟踪和取消 let downloadManager = KVHeavyTasksManager<URL, Data, Progress, CustomProvider>( config: .init( maxNumberOfRunningTasks: 2, // 最多同时 2 个下载 maxNumberOfQueueingTasks: 64 ) ) // 多个下载请求,自动队列管理 downloadManager.fetch( key: fileURL, customEventObserver: { progress in print("下载进度: \(progress.fractionCompleted)") }, result: { result in // 处理下载结果 } ) 

    2. MemoryCache:智能内存缓存系统

    let cache = MemoryCache<String, UIImage>( configuration: .init( // 内存限制 memoryUsageLimitation: .init(capacity: 1000, memory: 500), // 500MB // TTL 配置 defaultTTL: 3600.0, // 正常数据 1 小时过期 defaultTTLForNullElement: 300.0, // 空值 5 分钟过期 // 雪崩保护:随机化过期时间 ttlRandomizationRange: 60.0, // ±60 秒随机 // 内存成本计算 costProvider: { image in guard let cgImage = image.cgImage else { return 0 } return cgImage.bytesPerRow * cgImage.height } ) ) // 优先级缓存 cache.set(element: profileImage, for: "user-123", priority: 10.0) // 高优先级 cache.set(element: thumbnail, for: "thumb-456", priority: 1.0) // 低优先级 cache.set(element: nil, for: "missing-789") // 缓存"未找到" // 智能获取 switch cache.getElement(for: "user-123") { case .hitNonNullElement(let image): // 找到有效图片 displayImage(image) case .hitNullElement: // 找到"未找到"记录 showPlaceholder() case .miss: // 缓存未命中 loadImageFromNetwork() case .invalidKey: // 键值验证失败 handleInvalidKey() } 

    AI 辅助开发的实战经验

    1. Cursor 的惊人表现

    使用 Cursor 进行 AI 辅助开发最大的感受是:AI 比我想象的更"理解"代码

    代码审查能力

    当我写完核心逻辑后,Cursor 会提出改进建议:

    我的原始代码:

    func removeExpiredElements() { for key in keys { if isExpired(key) { remove(key) } } } 

    Cursor 的优化建议:

    func removeExpiredElements() -> Int { let keysToRemove = keys.filter { isExpired($0) } keysToRemove.forEach { remove($0) } return keysToRemove.count // 返回清理数量,便于监控 } 

    这种优化不仅提高了性能,还增加了实用功能,完全是我没想到的角度。

    单元测试的全面性

    最让我惊讶的是 AI 生成的单元测试。我只写了基本的功能测试,但 AI 补充的测试用例覆盖了很多我忽略的边界情况:

    // AI 生成的边界测试 func testConcurrentAccessWithSameKey() { // 测试多线程同时访问同一个 key } func testMemoryPressureEviction() { // 测试内存压力下的驱逐策略 } func testTTLRandomizationPreventsStampede() { // 测试 TTL 随机化防止缓存雪崩 } func testNullValueCaching() { // 测试空值缓存的各种场景 } 

    2. 不同 AI 模型的"个性"差异

    在开发过程中,我尝试了多个 AI 模型,发现它们确实有不同的"专长":

    GPT-4 的特点:

    • 保守但严谨:总是考虑各种异常情况
    • 注重边界处理:生成的代码防御性很强
    • 文档详细:API 文档写得非常全面

    Claude 的特点:

    • 性能敏感:经常提出性能优化建议
    • 代码优雅:生成的代码结构清晰,可读性强
    • 注重实用性:更关注实际使用场景

    Cursor 的特点:

    • 上下文理解强:能很好理解整个项目的结构
    • 实践导向:生成的代码更贴近实际开发需求
    • 工程化思维:关注 CI/CD 、项目配置等工程问题

    3. AI 协作的最佳实践

    经过两周的深度协作,我总结出几个关键的协作技巧:

    3.1 精确的需求描述

    模糊的描述:

    "我写了一个缓存, 帮我 review 一下"

    精确的描述:

    "我写了一个线程安全的内存缓存,支持 TTL 过期,优先级 LRU 淘汰策略,能够缓存 nil 值,防止缓存雪崩,并且可以设置内存使用上限, 请帮我 review 一下代码逻辑正确性 public API 的规范性以及合理性"

    3.2 迭代式优化

    不要指望 AI 一次性生成完美代码,而是通过多轮对话逐步优化:

    第 1 轮:实现基本功能 第 2 轮:添加异常处理 第 3 轮:优化性能 第 4 轮:完善文档 第 5 轮:添加单元测试 

    3.3 善用 AI 的不同视角

    对于关键代码,我会让不同的 AI 模型都 review 一遍,综合它们的建议:

    • GPT-4 帮我找 bug 和边界情况
    • Claude 帮我优化性能和代码结构
    • Cursor 帮我完善工程配置

    开发成果:5 个实战示例

    为了验证框架的实用性,我开发了 5 个真实场景的示例:

    1. Module Initialization - 模块初始化

    // 应用启动时的配置加载,支持重试和永久缓存 let cOnfigManager= AppConfigurationManager() configManager.initializeModule { result in switch result { case .success: print("配置加载成功") case .failure(let error): print("配置加载失败: \(error)") } } 

    2. User Profile Manager - 用户资料管理

    // 单用户资料管理,支持 TTL 刷新和强制更新 let profileManager = UserProfileManager() profileManager.setUser(firstName: "Alice") { result in // 设置完成后自动刷新缓存 } 

    3. Object Fetch Task - 批量对象获取

    // 三个 ViewModel 同时请求重叠的帖子 ID ,自动批处理 let repository = PostRepository() repository.getPostsBatch(ids: ["101", "102", "103"]) { results in // 批量处理结果 } 

    4. Large File Download Management - 大文件下载

    // Alamofire + AFNetworking 双 Provider 支持,断点续传 let downloadManager = AlamofireManager(config: .init()) let result = await downloadManager.asyncFetch( key: fileURL, customEventObserver: { progress in updateProgressBar(progress.fractionCompleted) } ) 

    5. Large File Unzip - 大文件解压

    // ZIPFoundation 集成,进度跟踪 let unzipManager = UnzipManager(config: .init()) unzipMaager.fetch( key: zipFileURL, customEventObserver: { event in switch event { case .progress(let percent): print("解压进度: \(percent * 100)%") } } ) 

    性能测试结果

    执行合并效果测试

    // 10 个并发请求测试 let startTime = CFAbsoluteTimeGetCurrent() await withTaskGroup(of: Void.self) { group in for i in 0..<10 { group.addTask { let result = await userTask.asyncExecute() print("Task \(i) completed: \(result)") } } } let duration = CFAbsoluteTimeGetCurrent() - startTime print("总耗时: \(duration)s, 网络请求次数: 1") 

    结果:10 个并发请求,只发出 1 个网络请求,所有回调都收到相同结果。

    缓存性能测试

    // 缓存命中率测试 let cache = MemoryCache<String, Data>(capacity: 1000) // 写入 10000 个条目 for i in 0..<10000 { cache.set(element: randomData(), for: "key\(i)") } // 随机访问测试 var hitCount = 0 for _ in 0..<1000 { let key = "key\(Int.random(in: 0..<10000))" if case .hitNOnNullElement= cache.getElement(for: key) { hitCount += 1 } } print("缓存命中率: \(Double(hitCount) / 1000.0)") 

    AI 协作开发的思考与展望

    对程序员职业的影响

    通过这次深度的 AI 协作开发经历,我对程序员这个职业有了新的思考:

    什么不会被 AI 取代:

    1. 架构设计能力:整体思维,权衡取舍
    2. 业务理解能力:理解用户需求,设计合适方案
    3. 创新思维:发现新问题,提出新解决方案
    4. 质量把控:判断代码质量,做技术决策

    什么会被 AI 大幅提升:

    1. 编码效率:重复性代码生成
    2. 测试覆盖率:边界用例发现
    3. 文档质量:规范化文档生成
    4. 代码质量:最佳实践建议

    未来的编程模式

    我认为未来的编程将是**"人机协作"**模式:

    程序员 = 产品经理 + 架构师 + 质量把控者 AI = 编码助手 + 测试工程师 + 文档工程师 

    程序员的价值将更多体现在创造性思维判断决策上,而不是纯粹的编码技能。

    对新手程序员的建议

    1. 尽早开始 AI 协作:不要等技术成熟,现在就开始学习
    2. 关注核心能力:专注算法、架构、业务理解等 AI 难以取代的能力
    3. 培养 AI 协作技能:学会如何与 AI 高效沟通,这将成为核心竞争力

    项目开源与社区反馈

    这个项目现在已经在 GitHub 开源:**github.com/yangchenlarkin/Monstra**

    技术特性

    • 零外部依赖:纯 Swift 实现
    • 全平台支持:iOS 13+, macOS 10.15+, tvOS 13+, watchOS 6.0+
    • 现代 Swift:支持 async/await ,Swift 5.5+
    • 完整文档:API 文档 + 5 个实战示例
    • 高测试覆盖率:AI 辅助生成的全面测试用例

    安装使用

    Swift Package Manager:

    dependencies: [ .package(url: "https://github.com/yangchenlarkin/Monstra.git", from: "0.1.0") ] 

    CocoaPods:

    pod 'Monstra', '~> 0.1.0' 

    总结

    这次 AI 辅助开发的经历让我深刻体会到:AI 不是要取代程序员,而是要让程序员变得更强大

    通过合理的分工协作,我们可以:

    • 将更多时间专注于创造性工作
    • 提高代码质量和文档水平
    • 加速项目开发进度
    • 学习到新的编程思路和最佳实践

    如果你还没有开始尝试 AI 辅助编程,我强烈建议你现在就开始。这不仅仅是一个工具,更是编程思维的升级。

    相关链接


    关于作者:iOS 开发工程师,专注于移动端性能优化和架构设计。这是我第一次深度尝试 AI 辅助开发,也是第一个开源项目。如果这个项目对你有帮助,欢迎在 GitHub 上给个,也欢迎提出改进建议!

    如果你有任何问题或想要交流 AI 辅助开发的经验,欢迎在评论区讨论,或者在 GitHub 上提 Issue 。让我们一起探索编程的未来!

    作者批

    上面的内容都是 Cursor 写的(甩锅 ing), 我这里补充几点:

    1. 任务合并和缓存, 在前端(React)框架中比较常见, 我的灵感也是来自于前端
    2. 文中的各个大模型的特点, 我并没有验证真伪, 这部分大家看个乐呵就好了. 不过我在写测试用例的过程中, 我确实真对同一个类, 让不同的大模型给我写测试用例, 然后让 Claude 给我整理 case 、去除重复 case 、规范命名和注释等. 然后我在去阅读这些 case, 发现有遗漏的 case 再让 AI 补充.
    3. 第三方库“要么功能不全,要么太重太复杂”, 这个有失偏颇, 我觉得大部分库还是功能不全, 我这个库才是太重太复杂 大家用的时候根据实际项目各取所需即可, 简单和全面在一定程度上本就是需要做取舍的.
    2 条回复    2025-09-09 14:22:39 +08:00
    WngShhng
        1
    WngShhng  
       107 天前
    为什么不直接用单例+内存缓存呢?
    HolidayBomb
        2
    HolidayBomb  
       106 天前 via iPhone
    从问题一,一看就是从 React 转来的吧?原生开发的这种场景和解决方式一般都不这样做,当然选择的方式也会有很多,看个人喜好了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1563 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 16:27 PVG 00:27 LAX 08:27 JFK 11:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86