当你使用 plank 命令自动生成一个类时
./plank --objc_class_prefix=PUG --no_runtime --no_recursive user.json
分析
在 JSON 目录下, 执行如上命令后, 生成的 PUGUser 对象, 会自带 copyWithBlock: 方法, 这个方法是用来做什么的 ?
copyWithBlock:
(注意末尾有一个冒号,因为它需要一个 Block 参数)是 Plank 为 每一个不可变模型类自动生成的“便捷变异”接口。它的核心作用可以概括为:
在保持原对象不可变的前提下做局部修改
Plank 生成的 PUGUser
属性全部是 readonly
。想改动其中某个字段时,你不能直接赋值,只能构造一个新实例。
copyWithBlock:
会先用当前对象创建一个 Builder (PUGUserBuilder
),把现有属性拷贝过去 → 你在 Block 里改 Builder 的可写属性 → Plank 再把 Builder build 成一个全新的 PUGUser
并返回。
整个过程中旧对象完全不变,线程安全、易于推导状态。(pinterest.github.io)
语法更简洁、可读性更好
与“自己手动 new Builder → 拷贝属性 → 设置新值 → build
”相比,它把所有模板代码都藏在方法内部,调用者只需已关注真正要改的字段:
PUGUser *updatedUser =
[originUser copyWithBlock:^(PUGUserBuilder *builder) {
builder.username = @"new_name";
builder.bio = @"喜欢 Objective-C 的人";
}];
这样一眼就能看出变动点。Plank 官方文档把它称为 fluent interface for mutation —— 一条链式语句即可完成复制 + 变更 + 生成。(pinterest.github.io)
与 mergeWithModel:
的区别
copyWithBlock:
:你显式地告诉 Builder 要改什么。
mergeWithModel:
:把另一个最新对象的“已设置字段”并入当前对象,用于渐进式加载(例如网络增量更新)。内部实现同样依赖 Builder,但合并逻辑由框架自动决定。
常见使用场景
UI 层拿到旧模型,用户修改昵称 / 头像等局部信息,立即生成新模型推送给上层数据流。
在自建数据同步层(例如通过通知分发模型变更)时,用 copyWithBlock:
保证每一次变更都会得到一个全新的、可比较的新对象,方便 diff 与渲染。(GitHub)
总结:
copyWithBlock:
就是 Plank 给不可变模型提供的“Builder-封装版 copy+局部修改”方法:
输入 = 旧对象 + 你的修改指令;
输出 = 一个只在指定字段上不同的新PUGUser
实例。
暂无评论内容