在这里插入图片描述

概述

各位似秃似不秃小码农们都知道,在苹果众多开发平台中 CoreData 无疑是那个最简洁、拥有“官方认证”且最具兼容性的数据库框架。使用它可以让我们非常方便的搭建出 App 所需要的持久存储体系。

在这里插入图片描述

不过,大家是否知道在 CoreData 中还存在一个 Transformable 类型,它到底是个啥?应用场景有哪些?在最新的 SwiftData 中有没有对应物?对于开发者又有哪些“见雀张罗”的撸码陷阱和最佳实践呢?

在本篇博文中,您将学到如下内容:

  • 概述
  • 6. 派生自 NSObject 的自定义类
    • 6.1 为 CoreData 中 Human 基类增加 skill 字段
    • 6.2 实现 Skill 数据结构
  • 总结

本系列文章一共包括将近 3w 枚机智而幽默的文字、详实的大段代码示例以及海量图片,定能让小伙伴们对 Transformable 类型的“驾驭”更加胸有成竹、胜券在握!

那还等什么呢?让我们马上开始 Transformable 大冒险吧!
Let’s go!!!😉


6. 派生自 NSObject 的自定义类

之前我们讨论了系统内置类、自定义结构等数据类型对于 Transformable 的支持,接下来,让我们再聊聊如何稳妥的处理自定义类的转换。

如若要我们自己的类也安全地支持 Transformable 类型,有两个条件:

  1. 必须派生自 NSObject 类;
  2. 必须遵守 NSSecureCoding 协议;

下面,我们就来实际撸码一回,看看具体的步骤是怎样的。

为了进一步拓展我们英雄和恶棍的战斗力,我们想为它们增加**技能(Skill)**这一超能力。我们这次希望用类的多态机制来适配不同种类 Human(英雄或恶棍)的 Skill。

6.1 为 CoreData 中 Human 基类增加 skill 字段

俗话说得好:“高楼平地起,基础不牢地动山摇”,我们首先要为 CoreData 中 Humam 基类增加支持 Skill 的字段:

在这里插入图片描述

从上图可以看到,我们主要做了以下几件事:

  1. 为 Human 托管基类增加 skill 字段,它的类型为 Transformable;
  2. 设置 skill 字段的 Transformer 属性为 SkillTransformer(待实现);
  3. 设置 skill 字段的 Custom Class 属性为 Skill(待实现);

这里再啰嗦几句,Transformable 字段的 Transformer 属性存放的是该字段实际类型到 Transformable 类型的转换器,而 Custom Class 则代表该字段的实际类型。

6.2 实现 Skill 数据结构

前面说过,我们希望英雄和恶棍的技能可以利用类的多态性来扩展,所以首先我们创建一个 Skill 抽象基类:

@objc(Skill)
public class Skill: NSObject, NSSecureCoding {let name: Stringinit(name: String) {if type(of: self) == Skill.self {fatalError("Skill 是抽象基类,禁止实例化!")}self.name = namesuper.init()}public class var supportsSecureCoding: Bool { true }public func encode(with coder: NSCoder) {coder.encode(name, forKey: "name")}required public init(coder: NSCoder) {name = coder.decodeObject(of: NSString.self, forKey: "name")! as Stringsuper.init()}
}

在 Skill 抽象基类的实现中,我们有几点需要注意:

  • 抽象基类应该禁止实例化,因为 Swift 语言本身没有提供静态的禁止方法,所以我们只能通过动态判断来达成;
  • Skill 内部应该存放所有子类共享的数据,比如 name;
  • Skill 需要实现 supportsSecureCoding 属性并返回 true,表示它支持安全编码;
  • Skill 应该实现 NSSecureCoding 协议所要求的两个方法,它们分别被用来做数据的编码和解码工作;
  • Skill 的类名称需要用 @objc 关键字将 Swift 的类名暴露给 objc 层,否则运行会提示找不到名为 Skill 的类;

随后,我们需要分别实现英雄和恶棍的技能,它们应该是 Skill 的子类:

/// 英雄技能
@objc(HeroSkill)
class HeroSkill: Skill {static let glare = HeroSkill(name: "英雄怒视", justicePower: 109, color: .pink)let justicePower: Intlet color: Colorinit(name: String, justicePower: Int, color: Color) {self.justicePower = justicePowerself.color = colorsuper.init(name: name)}override class var supportsSecureCoding: Bool { true }public override func encode(with coder: NSCoder) {coder.encode(justicePower, forKey: "justicePower")let uiColor = UIColor(color)coder.encode(uiColor, forKey: "uiColor")super.encode(with: coder)}required public init(coder: NSCoder) {justicePower = coder.decodeInteger(forKey: "justicePower")let uiColor = coder.decodeObject(of: UIColor.self, forKey: "uiColor")!color = Color(uiColor: uiColor)super.init(coder: coder)}
}/// 恶棍技能
@objc(VillainSkill)
class VillainSkill: Skill {static let swallow = VillainSkill(name: "恶棍吞咽", evalPower: 121)let evalPower: Intinit(name: String, evalPower: Int) {self.evalPower = evalPowersuper.init(name: name)}override class var supportsSecureCoding: Bool { true }public override func encode(with coder: NSCoder) {coder.encode(evalPower, forKey: "evalPower")super.encode(with: coder)}required public init(coder: NSCoder) {evalPower = coder.decodeInteger(forKey: "evalPower")super.init(coder: coder)}
}

对于上面 HeroSkill 和 VillainSkill 两个子类,我们实现了它们各自具体的数据编码和解密功能,并为它们分别创建了一个实例(glare 和 swallow)。

回想一下,之前我们为 Human.skill 字段的 Custom Class 设置的是 Skill 基类,而不是具体的子类,这意味着具体 Skill 子类的编码和解密工作都会由系统自动帮你搞定,真是妙哉妙哉!

在下一篇博文中,我们将继续完成 Skill 到 Transformable 类型的转换,等着你们哦!

总结

在本篇博文中,我们初步介绍了派生自 NSObject 的自定义类如何支持 Transformable 的转换,你值得拥有!

感谢观赏,我们下一篇再会啦!😎

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

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

相关文章

Vuex(一) —— 集中式的状态管理仓库

目录 Vue组件间通信方式回顾 组件内的状态管理流程组件间通信方式 父组件给子组件传值 (最简单的一种方式)子组件给父组件传值不相关组件之间传值其他常见方式($ref) 简易的状态管理方案 上面组件间通信方式的问题集中式的状态管理方案 Vuex 什么是Vuex?什么情况下使用Vuex?…

操作系统---内存管理上

文章目录 1. 内存的基础知识1.1 什么是内存,有何作用1.2 进程运行的基本原理1.2.1 指令的工作原理1.2.2 逻辑地址 VS 物理地址 1.3 如何实现地址转换(逻辑 -> 物理)1.3.1 绝对装入1.3.2 可重定位装入(静态重定位)1.…

医学图像处理期末复习

目录 考试范围第1章 绪论1.1 数字图像处理的概念1.2 数字图像处理的应用领域1、医学领域2、其他领域 1.3 数字图像处理基础1.4 数字图像基础运算 第2章 医学图像灰度变换与空间滤波2.1 医学图像灰度变换线性灰度变换非线性灰度变换 2.2 直方图均衡化√2.3 空间平滑滤波线性空间…

类图:软件世界的“建筑蓝图”

本文来自「大千AI助手」技术实战系列,专注用真话讲技术,拒绝过度包装。 类图(Class Diagram):软件世界的“建筑蓝图” 类图(Class Diagram)是统一建模语言(UML) 中最重要…

利用DevEco Studio对RK3588的HiHopesOS-4.1.110(OpenHarmony)进行Qt程序编写

文章目录 热身准备添加Qt库运行qml程序 热身 可以先看我这篇文章【DevEco Studio中使用Qt,编写HarmonyOS程序】 准备 板子的主要信息 目前由于系统版本(API 11)及其他原因,只能用4.1版本的DevEcoStudio来编写,更高…

设计模式精讲 Day 5:原型模式(Prototype Pattern)

【设计模式精讲 Day 5】原型模式(Prototype Pattern) 文章内容 在“设计模式精讲”系列的第5天,我们将深入讲解原型模式(Prototype Pattern)。作为创建型设计模式之一,原型模式通过复制已有对象来创建新对…

深度学习——第2章习题2-1分析为什么平方损失函数不适用于分类问题

深度学习——第2章习题2-1 《神经网络与深度学习》——邱锡鹏 2-1 分析为什么平方损失函数不适用于分类问题。 平方损失函数(Quadratic Loss Function)经常用在预测标签y为实数值的任务中,定义为 L ( y , f ( x ; θ ) ) 1 2 ( y − f (…

【Linux】运行脚本后打屏同时保存到本地

命令: sh run.sh 2>&1 | tee output.log sh run.sh 2>&1 | tee output_$(date "%Y%m%d%H%M").log作用:运行脚本,并同时将输出(包括标准输出和错误输出)显示到终端,并保存到文件中…

Spark 在小众日常场景中的实战应用:从小店数据到社区活动

Spark 在小众日常场景中的实战应用:从小店数据到社区活动​ 提起 Spark,大家往往会联想到大型互联网公司的数据处理、金融行业的复杂分析。但实际上,Spark 在许多小众、贴近生活的场景中也能大显身手。结合学习与实践,我探索了 S…

mysql 执行计划 explain命令 详解

explain id :select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序select_type:查询类型 或者是 其他操作类型table :正在访问哪个表partitions :匹配的分区type :访问的类…

让大模型“更懂人话”:对齐训练(RLHF DPO)全流程实战解析

网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…

GO 原子操作面试题及参考答案

Go 的 sync/atomic 包和 sync.Mutex 的根本区别是什么? Go 语言中的 sync/atomic 包和 sync.Mutex 都用于处理并发编程中的同步问题,但它们的实现机制、应用场景和性能特性存在根本差异。理解这些差异对于编写高效、安全的并发代码至关重要。 sync/atomi…

MATLAB 山脊图绘制全解析:从数据生成到可视化进阶

一、引言:当数据分布拥有「层次感」—— 山脊图的魅力​ 在数据可视化的世界里,我们常常需要同时展示多个分布的形态差异。传统的重叠密度图虽然能呈现整体趋势,但当分布数量较多时,曲线交叠会让画面变得杂乱。这时候&#xff0c…

跨境电商每周资讯—6.16-6.20

1. Instagram 在亚太地区逐渐超越 TikTok 在整个亚太地区,Instagram用户数量正逐渐超过TikTok。预计2025年日本Instagram用户数量将增至4440万,印度今年用户数量将增长10%,领跑亚太。与之形成对比的是,TikTok在一些国家增长速度放…

计算机网络 网络层:数据平面(一)

前一节学习了运输层依赖于网络层的主机到主机的通信服务,提供各种形式的进程到进程的通信。了解这种主机到主机通信服务的真实情况,是什么使得它工作起来的。 在本章和下一章,将学习网络层实际是怎样实现主机到主机的通信服务。与运输层和应用…

Suna本地部署详细教程

一、安装基础环境 # 1、创建环境 conda create -n suna python3.11.7# 2、激活虚拟环境 conda activate suna# 3、安装jupyter和ipykernel pip install jupyter ipykernel# 4、将虚拟环境添加到jupyter # python -m ipykernel install --user --namemyenv --display-name"…

LeetCode 每日一题打卡|若谷的刷题日记 3day--最长连续序列

1.最长连续序列 题目: 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入:nums [1…

EfficientVLA:面向视觉-语言-动作模型无训练的加速与压缩

25年6月来自上海交大、哈工大、西安交大和电子科大(成都)的论文“EfficientVLA: Training-Free Acceleration and Compression for Vision-Language-Action Models”。 视觉-语言-动作 (VLA) 模型,特别是基于扩散的架构,展现出具…

wireshark抓包分析TCP数据包

1、直接从TCP的三次握手开始说起 三次握手就是客户与服务器建立连接的过程 客户向服务器发送SYN(SEQ=x)报文,然后就会进入SYN_SEND状态服务器收到SYN报文之后,回应一个SYN(SEQ=y)ACK(ACK=x+1)报文,然后就会进入SYN_RECV状态客户收到服务器的SYN报文,回应一个ACK(AC…

同等学力申硕-计算机统考-历年真题和备考经验

同等学力申请硕士学位考试是比较适合在职人员的提升学位方式,了解过的人应该都知道,现在社会的竞争压力越来越大,为了提高职业生存能力,提升学位在所难免。 一、已有计算机统考历年真题资料 报名过同等学力申硕计算机专业的朋友都…