核心数据中的ValueTransformer解释:存储绝对URL

ValueTransformers in Core Data are a powerful way of transforming values before they get inserted into the database and get read. They’re set up in an abstract class that handles the value transformations from one representation to another.

Core Data中的ValueTransformers是在将值插入数据库并进行读取之前对其进行转换的强大方法。 它们设置在抽象类中,该抽象类处理从一种表示形式到另一种表示形式的值转换。

They’re often used as a way to store values that aren’t supported by default. Core Data allows you to save types like strings and integers, but storing a CGRect or CGPoint requires the usage of a ValueTransformer. Once you get to know how they work, you'll find out that you can use ValueTransformers for other cases too (e.g. storing an absolute URL as a relative one).

它们通常用作存储默认情况下不支持的值的方法。 核心数据允许您保存诸如字符串和整数之类的类型,但是存储CGRectCGPoint需要使用ValueTransformer。 了解了它们的工作原理后,您会发现也可以将ValueTransformers用于其他情况(例如,将绝对URL存储为相对URL)。

什么是ValueTransformer? (What Is a ValueTransformer?)

It’s all in the name: It transforms a value. More precisely, it transforms a value upon reading from and writing to the Core Data database.

一切都在名称中:它转换一个值。 更准确地说,它在读取和写入Core Data数据库时会转换一个值。

A ValueTransformer can take any type as input and return a value of a different type. An example is the transformation of a UIColor to NSData on insertion and converting it back from NSData to UIColor once it's read.

ValueTransformer可以采用任何类型作为输入,并返回不同类型的值。 一个例子是一个转型UIColorNSData嵌入和转换它从后面NSDataUIColor一旦它的读取。

如何在核心数据中使用ValueTransformers? (How Do I Use ValueTransformers in Core Data?)

A ValueTransformer is an abstract class that requires you to override and implement a few of its methods based on the transformation you are trying to achieve. Once a ValueTransformer is defined, it should be registered so that it’s available for your Core Data model. Finally, you can define a property as transformable and assign your custom transformer in the model representation.

ValueTransformer是一个抽象类,要求您根据要尝试实现的转换重写并实现其一些方法。 定义ValueTransformer后,应将其注册,以便可用于您的Core Data模型。 最后,您可以将属性定义为可转换,并在模型表示中分配自定义转换器。

创建一个ValueTransformer (Creating a ValueTransformer)

In this example, we’re going to create a transformer to convert a UIColor into NSData that we can store in our database.

在此示例中,我们将创建一个转换器将UIColor转换为NSData ,然后将其存储在数据库中。

We start by creating a new class called UIColorValueTransformer that inherits from ValueTransformer:

我们首先创建一个名为UIColorValueTransformer的新类,该类从ValueTransformer继承:

Core Data can basically be seen as a technology that wraps C function calls into an easier-to-use, object-oriented framework to manage an SQL database. It’s not built into Swift yet and therefore requires us to interact with Objective-C. The @objc attribute tells Swift to make our ValueTransformer available in Objective-C.

核心数据基本上可以看作是一种将C函数调用包装到易于使用的,面向对象的框架中以管理SQL数据库的技术。 它尚未内置到Swift中,因此需要我们与Objective-C进行交互。 @objc属性告诉Swift让我们的ValueTransformer在Objective-C中可用。

The next step is to set up our transformation logic, which we can do by overriding some of the methods that are available in the abstract ValueTransformer class. We start by defining the transformed value class and marking our transformer as reversible:

下一步是设置我们的转换逻辑,我们可以通过重写抽象ValueTransformer类中可用的一些方法来完成。 我们首先定义转换后的值类别,然后将变压器标记为可逆:

The transformedValueClass needs to return the type for a "read," a forward transformation. In our case, we would like to have a UIColor type upon reading a value from our persistent container.

transformedValueClass需要返回类型以进行“读取”(正向转换)。 在我们的例子中,当我们从持久性容器中读取一个值时,我们想要一个UIColor类型。

By defining our transformer as reversible, we basically tell Core Data that our transformer is able to handle both insertions and reads. In other cases, you might only want to transform a value upon insertion to make sure that the value conforms to certain requirements (e.g. storing a name with an uppercase first letter). In our case, however, we want to transform in both ways.

通过将我们的转换器定义为可逆的,我们基本上告诉Core Data我们的转换器能够处理插入和读取。 在其他情况下,您可能只想在插入时转换一个值,以确保该值符合某些要求(例如,存储带有大写首字母的名称)。 但是,就我们而言,我们想以两种方式进行转换。

转变价值 (Transforming the values)

Up next is implementing the actual transformation methods: one for reading from the database and one for writing to the database.

接下来是实现实际的转换方法:一种用于读取数据库,另一种用于写入数据库。

We make use of the NSKeyedArchiver class that allows us to read and store data using secure encoding, which is required since iOS 11 for improved security. We help ourselves during debugging by throwing an assertion if the transformation fails. Assertion failures are only triggered in debug builds, which is great in our case!

我们利用NSKeyedArchiver类,该类允许我们使用安全编码读取和存储数据,自iOS 11以来,这是提高安全性所必需的。 如果转换失败,我们会在调试期间通过声明来帮助自己。 断言失败仅在调试版本中触发,这在我们的情况下非常好!

注册变压器 (Registering the transformer)

The implementation of our ValueTransformer is mostly done. We only need a way to register it and make it available for our Core Data model.

我们的ValueTransformer的实现大部分已经完成。 我们只需要一种注册它并使之可用于我们的Core Data模型的方法。

We make use of a strongly typed name instead of defining our name as a static string. This prevents future mistakes if we decide to rename our transformer.

我们使用强类型名称,而不是将我们的名称定义为静态字符串。 如果我们决定重命名变压器,这可以防止将来出现错误。

The static register() method allows us to register the transformer as follows:

静态register()方法允许我们按以下方式注册转换器:

UIColorValueTransformer.register()

Make sure to do this before you set up your persistent container, as you will otherwise run into errors like this:

在设置持久性容器之前,请确保执行此操作,否则将遇到如下错误:

No NSValueTransformer with class name 'UIColorValueTransformer' was found for attribute 'color' on entity 'user'

通过连接ValueTransformer将属性设置为可变形的 (Setting up a property as transformable by connecting the ValueTransformer)

Finally, you need to connect your ValueTransformer to a property in your database. You do this by defining a property as transformable:

最后,您需要将ValueTransformer连接到数据库中的属性。 您可以通过将属性定义为可变形来实现:

Defining a property as transformable so that it can use a ValueTransformer.
Defining a property as transformable so that it can use a ValueTransformer.
将属性定义为可变形的,以便可以使用ValueTransformer。

You can connect the ValueTransformer in the Data Model Inspector:

您可以在数据模型检查器中连接ValueTransformer:

Connecting the value transformer inside the Core Data Model.
Connecting the ValueTransformer inside the Core Data model.
在核心数据模型内部连接ValueTransformer。

This is all you need to make use of your own ValueTransformer. In this case, to store a UIColor into a Core Data persistent container.

这就是您需要使用自己的ValueTransformer的全部。 在这种情况下,将UIColor存储到Core Data持久性容器中。

使用ValueTransformer将绝对URL存储为相对URL (Using a ValueTransformer to Store Absolute URLs as Relative URLs)

Now that you know how a ValueTransformer works, it’s time to explore other ways of implementing them.

现在您知道ValueTransformer的工作原理,是时候探索实现它们的其他方式了。

在核心数据中存储URL (Storing URLs in Core Data)

A common scenario in Core Data is storing URLs. iOS 11 introduced the URIAttributeType, which makes it tempting to store URLs directly into Core Data. This is fine in some cases, but it also makes storing absolute URLs a simple mistake, which can become a very big problem in the future.

Core Data中的一个常见方案是存储URL。 iOS 11引入了URIAttributeType ,它很容易将URL直接存储到Core Data中。 在某些情况下可以这样做,但是这也使存储绝对URL成为一个简单的错误,将来可能会成为一个非常大的问题。

URLs often point to directories like an App Group folder or the Documents directory. Some of those URLs are paths that can potentially change, as described in the documentation:

URL通常指向诸如App Group文件夹或Documents目录之类的目录。 其中一些URL是可能会更改的路径,如文档中所述:

“Always use the URL returned by this method to locate the group directory rather than manually constructing a URL with an explicit path. The exact location of the directory in the file system might change in future releases of macOS, but this method will always return the correct URL.”

“始终使用此方法返回的URL来定位组目录,而不是手动构造具有显式路径的URL。 在未来的macOS版本中,文件系统中目录的确切位置可能会更改,但是此方法将始终返回正确的URL。”

You might not always read the documentation carefully enough to prevent all cases, which is why I’d like to always take the safest route. This means that I store all my URLs relatively in Core Data.

您可能并不总是仔细阅读文档以防止出现任何情况,这就是为什么我想始终采用最安全的方法。 这意味着我将所有URL都相对存储在Core Data中。

为什么要使用ValueTransformer将绝对URL存储为相对URL? (Why should you use a ValueTransformer to store absolute URLs as relative URLs?)

You might wonder why you should use a ValueTransformer to store URLs as relative URLs. To prevent code like this:

您可能想知道为什么应该使用ValueTransformer将URL存储为相对URL。 为了防止这样的代码:

@NSManaged private var urlPath: String
public var url: URL? {
NSURL(fileURLWithPath: urlPath, relativeTo: RabbitInfo.shared.appGroupURL).absoluteURL
}

It’s much nicer to define our property like this:

像这样定义我们的属性会更好:

@NSManaged public var url: URL?

使用ValueTransformer将绝对URL转换为相对URL (Using a ValueTransformer to transform an absolute URL into a relative URL)

In this example, we’re storing a URL that’s pointing to a file in the App Group container. It fetches the app group URL from our config, which uses the FileManager to retrieve the right path:

在此示例中,我们在App Group容器中存储了指向文件的URL。 它从我们的配置中获取应用组URL,该配置使用FileManager检索正确的路径:

FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "YOUR_APP_GROUP_NAME")

The final implementation looks as follows:

最终实现如下所示:

As you can see, this ValueTransformer looks much like our earlier defined UIColor transformer. Upon inserting a new URL, the relative path is extracted and stored. Once the value is read, we append the current URL pointing to our App Group container. This way, we're sure to always reference the correct path and we'll never run into missing files.

如您所见,此ValueTransformer看起来很像我们之前定义的UIColor转换器。 插入新的URL后,将提取并存储相对路径。 读取值后,我们会将当前URL附加到指向我们的App Group容器。 这样,我们确保始终引用正确的路径,并且永远不会遇到丢失的文件。

那么什么时候应该使用URL属性类型呢? (So when should you use the URL attribute type?)

Only use the URL attribute type if you are sure that a path will not change in the future. Obviously, you can also use it for storing web URLs for which a transformer will not solve any future changes.

仅当您确定将来不会更改路径时,才使用URL属性类型。 显然,您也可以使用它来存储Web URL,而变压器将无法解决这些Web URL。

结论 (Conclusion)

ValueTransformers in Core Data allow you to transform values from any type into any other type. Storing a UIColor, CGRect, or other types can become possible by transforming them into NSData before insertion. ValueTransformers can also be used in other cases, like transforming a URL from absolute to relative.

Core Data中的ValueTransformers允许您将值从任何类型转换为任何其他类型。 通过在插入之前将UIColorCGRect或其他类型转换成NSData ,可以存储它们。 ValueTransformers也可以在其他情况下使用,例如将URL从绝对转换为相对。

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/better-programming/valuetransformer-in-core-data-explained-storing-absolute-urls-61ee37515690

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值