2.6 Data Types and Transformable Attributes
Not every data type is supported by Core Data. In this lesson, I will teach you which ones are supported, and I'll show you what to do when you need to store a custom data type.
1.Introduction2 lessons, 04:06
2.Core Data9 lessons, 1:04:07
3.Conclusion1 lesson, 00:53
2.6 Data Types and Transformable Attributes
Hi, and welcome back to Get Started with Core Data. In this lesson we will have an in depth look at data types and transformable attributes in Core Data. When you have a look at the list you can primarily see a lot of different numeric types. You have three different types of integer values with different length as well as a ten based decimal number. And single and double precision floating point numbers. When it comes to integers, use the size you need to save storage. For floating point numbers, I would recommend to only use doubles, because they're used almost everywhere for calculations. And storage and processing is not that much more efficient compared to single recession values. For currencies, definitely have a look at decimals. It will automatically convert to NSDecimalnumber in your app. Actually, there are even more numeric values that don't look like it. Dates are stored as double precision intervals since a reference date, here, January 1st, 2001 at midnight UTC. And booleans are stored as single digit numbers containing either zero or one. Now to the more interesting data types. Binary data can either be used to directly store, for instance, images. Or indirectly as transformables, which we will look at in a minute. When handling binary data you can allow external storage, which are generally turned on. This allows Core Data to store large binary data on the file system instead of the database. The underlying SQLite store can handle binary sizes up to 100 kilobytes somewhat efficiently. But anything larger than that has a major impact on performance. Strings are another basic data type. Core Data has full Unicode support and storing strings is a no brainer. But due to this it can be quite complex to search and sort strings since every language has different expectations. I won't go into detail on this, but if you need it you want to have a look at string normalization. Meaning converting Unicode strings into ST representation while searching and sorting. Before we tackle the second main point of this lesson let me quickly talk about transient attributes. Those are not start in the database so why do you find them? If you do, they participate in the Core Data process. This means if an object gets changed the transient value will be thrown away to avoid stale data. The same happens when an object gets faulted. What is a fault? If you fetch a lot of data, the returned object won't to be filled with values by default, otherwise called materialization. Core Data will wait until you access a property to fully materialize this object in memory. If you have computed properties, though, you won't need to define them in Core Data. Now onto transformable data types, also called custom data types. Since the data is custom, Core Data doesn't have rules how to store it. We need a transformer to do so. Let's create an example transformer that will transform an array of color values into storable data. I'm going to create all related extensions and classes in this new file. First I want to extend collections of UIColor to have a variable colorData of type NSData. Here I need to map the RGB values. To access them I'm going to extend UIColor to return an array of UInt8 values. To fill all my color values, I can use the three pointers, red, green and blue to fill them. Finally, I will return an array of UInt8 values that contained the color components between 0 and 255. To transform them to NSData I can use this array with an unsafe buffer pointer and return an NSData object with the base address and the length of those values. To do the inverse and get a color value spec I need to extend NSData. I can use a property called colorValues that will store an optional array of UIColors. First we need to make sure that the values are passed in lots of 3. Then we can create an array with the same size as we have values and initialize them as you UInt8. And then use withUnsafeMutableBufferPointer to get the pointer to the color value and use memcpy to fill it with values. Finally, we can slice the data into lots of three and map them to create a new UIColor object each. We also have to create this convenience initializer to accept an array of UInt8 values. Convert the components into floats and divide them by 255. And then call the initializer with red, green, blue and alpha which reset to 1. This was a more or less complex transformation but it can be quite difficult to convert a custom object into NSData and back again. Now let's create a value transformer itself. We can subclass NSValueTransformer for that. Here we need to override two functions, transformedValues and reverseTransformedValue for the opposite direction. In the first function we expect an array of UIColors and then return the color data. The inverse, we'll expect NSData, and return the color values. There are also two additional functions we can override. One is allowsReverseTransformation, which returns a Boolean, and we want to set it to true. The second one is TransformedValueClass, which returns a class, here, NSData. We also need to register the value transformer and we can do that, for instance, during the creation of the stack. NSValueTransformer has a method, setValueTransformer forName. It will take the initialized class and a name for it, in our case, ColorTransformer. In the Call Data editor we can now use this ColorTransformer by referencing it in the properties. Before we wrap up the lesson I want to tell you about dynamic default values. You can set a default in the editor, but it is static. For instance, the date. If you want to use the current date you have to do it in code. For that you can use primitive properties which other backing store of Core Data. And shouldn't be used directly, except when creating custom accesses. Here we are going to override awakeFromInsert to set the primitive date to the current date. In the next lesson, I will teach you how to sort your data with predicates. See you there.