3

As you can see the image, I totally mess up the Data Type (The red circle). Is there a way to change the Data Type into Integer?

EDIT

I want to change the data type from a String to an Int and I have existing data so I can't start with a fresh realm and just change the var type.

class Item: Object {
    @objc dynamic var name: String?
    @objc dynamic var itemid: String?
    @objc dynamic var cateid: String?
}

enter image description here

Jay
  • 34,438
  • 18
  • 52
  • 81
kit
  • 1,166
  • 5
  • 16
  • 23
  • 1
    Just change the type of your variables to `Int`. You should also [edit] your question to include the Realm model definitions instead of a screenshot of your db to make the question on-topic. – Dávid Pásztor Dec 13 '19 at 09:50
  • @DávidPásztor I may have missed something or not understood the question but won't changing the primitive type for an existing model with data throw a migration error? See my answer for what I mean. – Jay Dec 13 '19 at 19:15
  • @Jay OP didn't ask about migrating an existing database, only changing the data type :) For sure, if you want to convert an existing database, you need to implement the migration block – Dávid Pásztor Dec 13 '19 at 19:18
  • @DávidPásztor Thanks for the clarification. I was looking at the existing data shown in the screen shot - wasn't sure if that was a factor. For clarification, if the object model has been accessed in any way, (as in: `let items = realm.object(Item.self)` ) even if no data has ever been written, that model will exist in the Realm file and if a String is changed to an Int, it will throw the migration error. – Jay Dec 13 '19 at 19:28

2 Answers2

2

I may have misunderstand the question but you appear to have existing data stored as as a String and you want to 'convert' all of those to an Int.

You cannot directly change the type to another type and have the stored data changed as well. If you do, it will be flagged with an error.

Error!
  Migration is required due to the following errors:
- Property 'Item.itemid' has been changed from 'string' to 'int'.

You need to incorporate a migration block to 'convert' the string value to an Int. Assuming we add a new Int property to our object `item_id', something along these lines will migrate your strings to int's and in the case where the string is not a valid it, it will be assigned a value of 0

Realm.Configuration.defaultConfiguration = Realm.Configuration(
schemaVersion: 1,
migrationBlock: { migration, oldSchemaVersion in
    if (oldSchemaVersion < 1) {
        migration.enumerateObjects(ofType: Item.className()) { oldObject, newObject in
            let stringValue = oldObject!["itemid"] as! String
            newObject!["item_id"] = Int(stringValue) ?? 0
        }
    }
})

Also, as soon as Realm is accessed, the object models are written to the Realm file. So a simple matter of

let items = realm.object(Item.self)

Will store that model even if no data was ever written. If, after that line, the var type is changed from a String to an Int, it will throw the migration error.

Deleting the Realm and starting from scratch is one option if that's the case, and as mentioned above, a migration block.

If this is brand new model that has never been used, then as the comments and other answer suggest, just change the String to an Int.

Jay
  • 34,438
  • 18
  • 52
  • 81
  • Hi Jay, can you help me edit my question? It seems like my question not so clearly... But your answer is the thing that I wanted to do. – kit Dec 14 '19 at 01:10
  • @kit Sure! I added small edit to the question for clarification - it was fairly clear to me to start with. Glad the answer helped. – Jay Dec 14 '19 at 14:18
0

Simply change the String to Int in your Object model. Please note that the Realm documentation says:

String, NSDate, and NSData properties can be declared as optional or non-optional using the standard Swift syntax.

So unlike the String in your previous model, you will not be able to declare your Int as optional. You have two options:

  1. Declare a default value:

    class Item: Object {
       @objc dynamic var name: String?
       @objc dynamic var itemid: Int = 0
       @objc dynamic var cateid: Int = 0
    }
    
  2. Declare it as a RealmOptional:

    class Item: Object {
       @objc dynamic var name: String?
       @objc dynamic var itemid = RealmOptional<Int>()
       @objc dynamic var cateid = RealmOptional<Int>()
    }
    

For more information on each solution please see this SO answer and the Realm documentation.

lajosdeme
  • 2,189
  • 1
  • 11
  • 20