背着房贷写Core Data:一个杭州码农的深夜碎碎念
凌晨一点半,杭州滨江,刚把娃哄睡。房贷还有23年,每个月1万2。我坐在电脑前,决定聊聊Core Data。
一、那个让我破防的晚上
去年十月的一个周五晚上,大概九点多,我从公司楼下沙县小吃打包了一份拌面加鸡腿,挤上地铁1号线。从滨江站到余杭,整整1小时40分钟。地铁上信号断断续续,我刷着技术公众号,看到一篇《2023年iOS开发者生存现状》,里面写了句:"30岁以上的iOS开发,如果还在写CRUD,基本等于等死。"
我当时心里咯噔一下。
我叫老陈,今年31,坐标杭州,在一家做智能硬件的公司干iOS开发。月薪22k,听着还行对吧?但扣完五险一金到手17k出头,房贷1万2,老婆全职带娃没收入,每个月的生活费、奶粉钱、物业费加起来怎么也得5k。算下来,每个月能存下的钱,还不够应对一次突发状况。
那天晚上回到家,老婆已经睡了,娃也睡了。我坐在客厅沙发上,吃着已经坨了的拌面,打开手机看了看银行卡余额:8632.47。
"操。"
就一个字,但包含了所有情绪。
我打开电脑,不是为了刷剧,也不是为了打游戏。我开始想:我他妈还能干点啥?
然后我打开了Xcode,决定写一篇关于Core Data的技术笔记。不是为了装逼,是为了让自己清醒一点——31岁了,连自己吃饭的家伙事儿都没整明白,还谈什么未来?
二、Core Data到底是个啥?先别急着骂
我知道,一提到Core Data,很多iOS开发就翻白眼。"这玩意儿又老又难用,谁还在用啊?""直接上SQLite不香吗?""Realm不香吗?SwiftData不香吗?"
兄弟,你先别急。
我先问你一个问题:你每天挤地铁的时候,手机上的App离线数据是怎么存的?你用的那个记账App,断网了还能不能看账单?你用的那个笔记App, airplane mode下还能不能编辑?
数据持久化,是iOS开发的基本功,不是选修课。
Core Data是Apple官方提供的数据持久化框架,从iOS 3.0就有了,比我入行都早。它不是数据库,它是一个对象图管理和持久化框架。这句话很重要,划重点。
什么意思呢?就是说Core Data的核心职责不是帮你存数据,而是帮你管理对象之间的关系和生命周期。它底层可以用SQLite、XML、二进制甚至内存来存储,但你在代码层面操作的是对象,不是SQL语句。
这就像你老婆管你的工资卡。钱是存在银行里的(SQLite),但你老婆关心的是:这个月花了多少、存了多少、给娃买了啥(对象关系)。她不需要知道银行底层怎么运作的。
三、架构设计思考:别把Core Data当SQLite用
我见过太多人把Core Data当SQLite用,写出来的代码又臭又长,然后反过来说Core Data垃圾。这就像你用菜刀砍树,然后说菜刀不好用。
Core Data的正确打开方式,是从架构层面去思考的。
3.1 分层架构:别让ViewController碰NSManagedObjectContext
这是我踩过最大的坑。刚学Core Data的时候,我直接在ViewController里创建context,然后fetch、insert、delete,搞得ViewController又胖又臭。后来重构的时候,差点没把自己送走。
正确的做法是分层:
┌─────────────────────────────┐
│ View Layer (UIKit) │ ← 只管展示,别碰数据
├─────────────────────────────┤
│ ViewModel / Presenter │ ← 业务逻辑在这层
├─────────────────────────────┤
│ Repository / DAO Layer │ ← 封装Core Data操作
├─────────────────────────────┤
│ Core Data Stack │ ← 持久化栈,统一管理
└─────────────────────────────┘
Repository层封装所有的Core Data操作,对外暴露干净的方法。ViewModel层调用Repository,不关心底层是Core Data还是Realm还是啥。View层只管绑定数据、响应用户操作。
这样的好处是:哪天你想把Core Data换成SwiftData,只需要改Repository层的实现,其他层基本不用动。这就是面向接口编程的魅力。
3.2 线程模型:搞不懂这个,等着crash吧
Core Data的线程模型是很多人踩坑的重灾区。记住一句话:NSManagedObjectContext是线程不安全的。每个context只能在一个线程/队列里用,跨线程访问必crash。
Apple推荐的线程模型是:
主线程 Context (Main Queue)
↑ 子context (parent)
子线程 Context (Private Queue)
↑ 主context (parent)
Persistent Store Coordinator
在子线程做耗时的读写操作,完成后merge回主线程context,主线程context负责UI展示。这样既保证了性能,又保证了线程安全。
// 后台context做批量导入
let backgroundContext = persistentContainer.newBackgroundContext()
backgroundContext.perform {
for item in hugeDataArray {
let entity = MyEntity(context: backgroundContext)
entity.name = item.name
entity.value = item.value
}
try? backgroundContext.save()
}
// 主线程context自动merge变化
NotificationCenter.default.addObserver(
self,
selector: #selector(contextDidSave(_:)),
name: .NSManagedObjectContextDidSave,
object: backgroundContext
)
3.3 数据迁移:别等出事了才想起来
很多人做Core Data的时候,根本不管数据迁移。觉得"我就一个demo,迁移个屁"。结果上线后,加了个字段,老用户一更新App,直接crash,数据全丢。
数据迁移是架构设计的一部分,不是事后补丁。
Core Data支持轻量级迁移(Lightweight Migration)和重量级迁移(Custom Migration)。轻量级迁移能处理加字段、删字段、改属性类型等简单场景,重量级迁移能处理更复杂的数据结构变化。
我的建议是:从第一天就开启轻量级迁移。
let description = NSPersistentStoreDescription(url: storeURL)
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true
这两行代码,关键时刻能救你的命。别问我怎么知道的。
四、说说Tabnine和Agent工作流:码农的效率革命
写到这里,我喝了口水,看了一眼时间,凌晨两点半。老婆翻了个身,嘟囔了一句"别熬太晚"。我应了一声,但没停下。
因为接下来我要聊的东西,是真正让我觉得"这日子还有盼头"的关键。
4.1 Tabnine:我的第二个大脑
今年年初,我月薪从22k涨到了25k。不是因为公司大发慈悲,是因为我跳槽了。面试的时候,面试官问我:"你平时怎么写代码的?效率怎么样?"
我说:"我用Tabnine。"
面试官愣了一下,然后笑了:"不错,跟我一样。"
Tabnine是一个AI代码补全工具,跟Copilot类似,但有几个关键区别:
- 支持本地模型:可以在本地跑,代码不上云,对公司代码安全友好
- 支持更多IDE:Xcode、VS Code、JetBrains全家桶都行
- 补全质量高:尤其是Swift/Objective-C这种相对小众的语言,Tabnine的表现比Copilot更稳定
举个真实例子。上周我在写Core Data的Repository层,需要写一堆CRUD方法。以前这种活儿,我得对着文档一个一个敲,一个方法少说5分钟。现在呢?我写完方法签名,Tabnine直接把实现补全了,连错误处理都给你写好了。
// 我只写了这一行
func fetchUsers(with predicate: NSPredicate?) -> [User] {
// Tabnine自动补全了下面所有代码
let fetchRequest = User.fetchRequest()
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
do {
return try context.fetch(fetchRequest)
} catch {
print("Fetch users failed: \(error)")
return []
}
}
省下来的时间干嘛?思考架构啊兄弟。
以前我一天能写500行代码,但大部分是重复劳动。现在我一天写200行,但每一行都是经过思考的。代码质量上去了,bug少了,加班也少了。
4.2 Agent工作流:从"写代码"到"指挥AI写代码"
如果说Tabnine是"AI帮你补全代码",那Agent工作流就是"AI帮你完成任务"。
这是今年最火的概念之一。简单来说,Agent就是一个能自主完成多步骤任务的AI系统。你给它一个目标,它会自己拆解任务、调用工具、执行操作、检查结果,直到任务完成。
举个我在实际项目中的例子。
我们公司有个内部工具,需要把后端API返回的JSON数据映射到Core Data模型。以前这个活儿是手动干的:看JSON结构,建Core Data模型,写映射代码,测试。一个模型少说半小时。
现在我搞了个Agent工作流:
- 输入:JSON Schema + Core Data模型模板
- Agent拆解任务:解析JSON → 生成实体类 → 生成映射代码 → 生成单元测试
- 执行:调用LLM生成代码,自动写入项目文件
- 检查:跑单元测试,失败了自动修复,直到通过
整个过程我只需要review最终代码,确认没问题就提交。以前半天的活儿,现在20分钟搞定。
这就是Agent工作流的威力:不是替代你,而是放大你。
你的价值不再是"能写多少行代码",而是"能设计多好的系统"。AI负责执行,你负责决策。
五、深夜的思考:31岁,路在何方?
凌晨三点,我写完了最后一行代码,关上电脑。
窗外是杭州滨江的夜景,远处是阿里园区的灯光,还亮着。我想起去年面试的时候,面试官问我:"你对未来有什么规划?"
我当时说:"我想成为架构师。"
面试官笑了笑:"架构师不是title,是能力。你现在连自己项目的数据层都没想清楚,谈什么架构?"
那句话像一巴掌,把我打醒了。
是的,我一直在逃避。
逃避什么?逃避思考。每天上班写业务代码,下班刷短视频,周末带娃。看似很忙,其实是在用战术上的勤奋掩盖战略上的懒惰。
Core Data用了三年,我连它的线程模型都没搞明白。MVVM说了两年,我写的代码还是MVC。AI工具出来一年了,我还在手动写重复代码。
这不是努力,这是自我感动。
六、给同龄人的几句掏心窝子的话
如果你也是30+的iOS开发,也在背着房贷养着娃,也在迷茫未来在哪,我想跟你说几句:
6.1 基本功不能丢
别整天追新框架、新概念。Core Data、Runtime、Runloop、内存管理,这些老东西才是你的根基。框架会变,但底层原理不会。搞懂了Core Data的线程模型,你换SwiftData也能快速上手。搞懂了Runtime,你看任何OC框架的源码都不怵。
6.2 学会用AI,但别依赖AI
Tabnine、Copilot、Claude,这些工具能帮你提效,但不能帮你思考。你可以让AI帮你写代码,但你必须知道为什么这么写。否则你就是一个"代码搬运工",AI升级了,你就失业了。
6.3 跳出舒适区
我今年做了三件事:
- 把项目的数据层从Core Data重构成了Repository模式
- 搭了一套Agent工作流,自动化了50%的重复工作
- 开始写技术博客,逼自己把知识体系化
这三件事,没有一件是领导要求的。但就是这三件事,让我在面试的时候有了底气,让我从22k涨到了25k。
6.4 别跟年轻人比体力,要比脑子
25岁的年轻人能加班到凌晨两点,你不行。他们有精力学新框架,你学完就忘。但你有一样东西他们没有:经验。
你踩过坑,你知道哪些方案是坑,哪些设计是坑。你见过线上事故,你知道什么代码会导致OOM,什么架构会导致耦合。这些东西,是时间换来的,是AI替代不了的。
把经验体系化,把体系化变成方法论,把方法论变成架构能力。这才是30+程序员的核心竞争力。
七、写在最后
现在是凌晨三点半,娃明天还要上早教课,我得睡了。
写完这篇文章,我心里舒服多了。不是因为写得多好,是因为我终于把脑子里的东西倒出来了。
Core Data是个老框架,但它背后的设计思想——对象图管理、分层架构、线程安全、数据迁移——这些东西放到任何框架里都适用。
Tabnine和Agent工作流是新工具,但它们背后的逻辑——用AI放大人的能力、把重复劳动交给机器、把思考留给自己——这些东西才是未来的方向。
技术会过时,但思考不会。
明天还要早起挤地铁,1小时40分钟,从余杭到滨江。但我不怕了。因为我知道,地铁上的那1小时40分钟,不是垃圾时间,是我唯一能安静思考的时间。
我会戴着耳机,听着技术播客,在脑子里过一遍今天的代码,想想哪里可以优化,哪里可以重构。
这就是一个31岁杭州码农的日常。没有逆袭,没有暴富,只有每天进步一点点的坚持。
共勉。
老陈,2024年某日凌晨,于杭州余杭
P.S. 如果你也在学Core Data,推荐你看看Apple官方的《Core Data Programming Guide》,虽然老了点,但设计思想讲得很透。别只看教程,要看官方文档。
P.P.S. 房贷还有23年,但我不慌了。因为我知道,只要还在思考,就还没输。


评论 0