Core Data
OneGen supports generating full-featured Core Data models including its managing model
file (xcdatamodel
). In this article, you'll learn everything you need to know to successfully
use Core Data with OneGen-generated models in your app.
Setup
New Project
If you're starting a new project, make sure to select the Use Core Data checkbox in the dialog. It will make Xcode generate the following:
-
Data model file: a new file in your project
your_project_name.xcdatamodeld
. You can delete this file as OneGen will generate it for you. -
Model loading code: a function or file loading the data model file. Try to find
the statement that loads the model file. It will probably look similar to this:
NSPersistentContainer(name: "your_project_name")
. Replace the your_project_name with model, as that's what OneGen names this data model file.
Existing Project
If you're not sure how to implement the boilerplate code to load a core data model file, we suggest creating a new project and just copying the code over to your existing project. Just make sure to change the model file name to model when loading it as described above.
Enums
Since Enums can't be represented in Core Data, or rather in Objective-C, OneGen found a workaround, so you can still comfortably use Enums.
Enums get generated, but they are not stored in Core Data. If you reference an enum in your model, OneGen would generate a field with the enum's underlying data type and on top of that create a computed variable that converts from/to the enum type.
Let's consider the following example. We defined an enum named Color
that contains some colors.
We also defined a class User
and we'd like to store our users' eye color in
a new field eyeColor: Color
. Now take a look below at how OneGen would deal with these models
in compliance with Core Data.
// Color.swift
enum Color: String, Codable {
case green = "GREEN"
case blue = "BLUE"
case red = "RED"
}
// User.swift
class User: NSManagedObject, Codable {
// The enum's underlying String value is saved in Core Data
@NSManaged open var eyeColorValue: String
// OneGen generates a computed variable
// to conveniently work with the Color enum
var eyeColor: Color {
get {
return Color(rawValue: self.eyeColorValue)!
}
set {
self.eyeColorValue = newValue.rawValue
}
}
}
Data Types
There are certain limitations when it comes to Core Data. OneGen modifies some model data types to make sure everything is aligned with Core Data.
Optional data types
You may have marked some data types optional and noticed they're not optional in the generated code. There are certain data types that can't be marked optional in Core Data.
Design Data Type | Swift Data Type |
---|---|
Numeric Data Types (uint, int, float, double) | UInt, Int, Float, Double |
bool | Bool |
byte | UInt8 |
Int without size
While Swift supports Int without the size specification, Core Data does not. OneGen
translates Int
to Integer 64
in Core Data.
Unsigned integer types
As Core Data doesn't have native unsigned integer types, OneGen generates them as signed. Hence
UInt32
would become Integer 32
in Core Data.
Enums inside an array/map
If your data type is an array or a map that involves an Enum, all Enum types will be replaced with their
underlying data type. For example, if you have this property: colors: [Color]
where
Color
is defined as a string enum, it would be generated
as: colors: [String]
If you reference a standalone Enum, it will work as described above in the Enum section.
Transformable
Some complex data types can be represented as Transformable in Core Data. OneGen takes advantage of this feature in the following cases:
Data Type | Info |
---|---|
Array | Arrays get marked as Transformable unless the array is a relationship. |
Map | Maps (Dictionaries) always get marked as Transformable |
If your models contain a Transformable type, make sure to read about it on the Apple Docs.
Relationships
Core Data supports the following types of relationships:
- One to One: for example, one
Person
has oneHouse
- One to Many: for example, one
Person
has multipleDog
s - Many to Many: for example, multiple
Person
s study multipleCourse
s and eachCourse
has manyPerson
s
Inverse Relationship
Core Data recommends using inverse relationships. It essentially means
if a Person
references a House
, then the House
should reference the Person
as well.
OneGen automatically locates inverse relationships if they exist and marks them as such. There is one edge case when this automatic process won't work correctly though.
Multiple properties reference the same type
Let's say you have two classes Note
and User
. A User can have many notes, thus
we'd create a one-to-many relationship. As for the inverse relationship, imagine we want to have two
references from Note
to User
as shown in the code below:
class User {
var notes: [Note]
}
class Note {
var author: User?
var editor: User? // imagine a feature where we can invite an editor to edit our note
}
OneGen automatic inverse relationship lookup wouldn't be able to resolve this automatically, so you would
have to manually fix the relationships in the xcdatamodel
file.