Populating Lists during migration

(Mark spaulding) #1

Hi All,

I have an app that previous uses Results type to populate a Tableview. I converted this to a List.

When I add new data to the database all work just fine. My problem is the data the user may already have in the database, it does not copy over to the List at all.

I am guessing this is a migration problem, I just not sure how to go about it.

Any help would be greatly appreciated!


(Zsolt Jandzso) #2

Do you use migration block for the database schema change? If yes, can you share it?

(Mark spaulding) #3

Hi Thanks for the consideration.

This is what I am using, and it creates the new Model for the lists, but does not copy the records in the original model, Registry and adds them to the list.

There must be a command to do this, just can’t figure it out.

migrationBlock: { migration, oldSchemaVersion in
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically

                //Add migration here!
                migration.enumerateObjects(ofType: AllServices.className()) { oldObject, newObject in
                    // combine name fields into a single field
                    newObject!["everything"] = List<Registry>()
                    newObject!["eucharist"] = List<Registry>()
                    newObject!["weekdayEucharist"] = List<Registry>()
                    newObject!["office"] = List<Registry>()
                    newObject!["marriage"] = List<Registry>()
                    newObject!["burial"] = List<Registry>()
                    newObject!["requiem"] = List<Registry>()
                    newObject!["nuptial"] = List<Registry>()
                    newObject!["other"] = List<Registry>()


(Zsolt Jandzso) #4

Yeah, you are not using the oldObject for anything, just create an empty newObject.

(Mark spaulding) #5

Thanks for the reply!

Yes, this is where I am stuck. Not sure of the syntax since the oldObjects are in a different Model. This is a partial list:

class Registry: Object {

//Date, time, place and type
@objc dynamic var registryId = UUID().uuidString

@objc dynamic var dateTime:String?
@objc dynamic var proper:String?
@objc dynamic var service:String?
@objc dynamic var place:String?

I need this data, if it is there, to be accessed in each of the lists that the user has already saved to Registry.

When I add a new record it saves the data to the correct list no problem, Just can’t figure out how to reference the already saved data when migrating an update.

Any pointers you can send my way would be much appreciated. I can’t find any documentation on how to do this.


(Zsolt Jandzso) #6

The syntax is the same as on the newObject.

You can access to the properties as dictionaries, so something like this:

newObject[“place”] = oldObject[“place”]

You can find the documentation here: https://realm.io/docs/swift/latest#updating-values

(Mark spaulding) #7

Thanks so much for the syntax!

I will have to experiment and see if I cannot the logic in my head.

Thanks again.

(Mark spaulding) #8

Hi Again,

Thanks again for the reply.

I adjusted the migration block (below, but I removed all but three of the columns) and the app runs without a crash which is an improvement, but I still have empty records in the List Object.

The Registry model stores all the data
The AllServices model contains all the data for a specified service type.

When I add a new entry, it shows up as expected.

Thanks again for the help!

migration.enumerateObjects(ofType: AllServices.className()) { oldObject, newObject in

                    let registryId = oldObject!["registryId"] as! String
                    let dateTime = oldObject!["dateTime"] as! String
                    let service = oldObject!["service"] as! String
                    let place = oldObject!["place"] as! String
                    let sunEuchAttendance = oldObject!["sunEuchAttendance"] as! Int
                    let otherServiceAttendance = oldObject!["otherServiceAttendance"] as! Int
                    newObject!["registryId"] = oldObject?["registryId"]
                    newObject!["dateTime"] = oldObject?["dateTime"]
                    newObject!["service"] = oldObject?["service"]
                    newObject!["place"] = oldObject?["place"]
                    newObject!["sunEuchAttendance"] = oldObject?["sunEuchAttendance"]
                    newObject!["otherServiceAttendance"] = oldObject?["otherServiceAttendance"]

(Zsolt Jandzso) #9

I don’t know what you are doing with those force-casts, but you are not using those properties.

You didn’t post your AllServices model, so i don’t really now, but if those properties are Lists then you are completely missing a few steps.

Here is how you should do:
1.) create a new list, with the type of property “var newList = List()”
2.) iterate over all of the old data and create a Registry from each of them “let newData = Registry.init(…)”
3.) add those data to the newList “newList.add(newData)”
4.) set the newData new property to the newList “newObject[“listProperty”] = newList”

(Mark spaulding) #10

Thanks you so much, this is incredibly helpful.

Now I have a direction to get this project moving.

Thanks again!


(Mark spaulding) #11


I am clearly missing something as I get a bunch of errors: List() requires an Element but I am not sure what it is asking for, and newList. Add error says List does not have the command Add.

Here are my models The first is the original:

class Registry: Object {

//Date, time, place and type
@objc dynamic var registryId = UUID().uuidString

@objc dynamic var dateTime:String?
@objc dynamic var proper:String?
@objc dynamic var service:String?
@objc dynamic var place:String?

@objc dynamic var sunEuchAttendance:Int = 0

//All Other services
@objc dynamic var otherServiceAttendance:Int = 0
@objc dynamic var EuchVisitor:Int = 0

@objc dynamic var numberOfCommunions:Int = 0

//People serving
@objc dynamic var presiderOfficiant:String?
@objc dynamic var preacher:String?
@objc dynamic var server:String?
@objc dynamic var memo:String?

@objc dynamic var weekendEuch:Int = 0
@objc dynamic var weekdayEuch:Int = 0
@objc dynamic var privateEuch:Int = 0

@objc dynamic var weekendOffice:Int = 0
@objc dynamic var weekdayOffice:Int = 0

//Other services
@objc dynamic var burrial:Int = 0
@objc dynamic var marraige:Int = 0

//Other services and memos
@objc dynamic var other:Int = 0

override static func primaryKey() -> String? {
    return "registryId"

override static func indexedProperties() -> [String] {
    return ["service"]


And I am updating the app to include lists so this needs to be migrated:

class AllServices: Object {

var everything = List<Registry>()
var eucharist = List<Registry>()
var weekdayEucharist = List<Registry>()
var office = List<Registry>()
var weekdayOffice = List<Registry>()
var marriage = List<Registry>()
var burial = List<Registry>()
var requiem = List<Registry>()
var nuptial = List<Registry>()
var other = List<Registry>()


Thanks so much for the help!

(Zsolt Jandzso) #12

If there is no data for one list, then you should not migrate that list. Otherwise, dont forget to add elements to the lists.

I am curious, why do you use the same Registry model for all the lists? That pretty redundant.
Its easier to do with one list and a type field on the Registry model.

(Mark spaulding) #13

Hi thanks for the reply.

Each of the Lists needs the saved data in the Registry model and each list is presented to the user based on their selection. Each section will present different data saved to the Registry model for that list.

I assume the elements are the names of each variable that the particular List might use?


(Zsolt Jandzso) #14

It should be fine, however i don’t used it this way. Can you please try it with only one list property? If its working that way then we found the issue :slight_smile:

(Mark spaulding) #15

Thanks I will give that a try tonight. AT this pint I will try anything! :slight_smile:

Thanks again.