Getting error in realm when i try to add new property in realm object - swift

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error:
Error Domain=io.realm Code=1 "Provided schema version 0 is less than
last set version 1." UserInfo={NSLocalizedDescription=Provided schema
version 0 is less than last set version 1., Error Code=1}
Getting this error when I try to add new property in Realm
Not finding any solution for this in swiftui

That's a normal error you will receive during development as you are changing your model and properties around.
The schema version is set to 1 (or it was set to 1) and then you modified an object so you should set schema version to 2 via a migration.
From the docs
Realm Database can automatically migrate added properties, but you
must specify an updated schema version when you make these changes.
If you're just in development, you could also just delete the Realm file and the objects will be built again with schema version 1.
Please see the documentation for Realm Migrations.
We've do that a LOT during the early stages of development so we have a button in our UI that just deletes the Realm files - keeping in mind that upon app start, you cannot touch the realm file for this to work. Once you've touched it, it's 'open' and cannot be deleted through code.
func deleteRealm() {
do {
//return the config pointing to where the realm file is located - we
// keep ours in the project folder initially
let config = gGetConfig()
let isSuccess = try Realm.deleteFiles(for: config)
print("deleted realm: \(isSuccess)")
} catch let err as NSError {
print(err.localizedDescription)
}
}
Edit: Sometimes you can nil the Realm out and then delete it via code but Realm is quite stubborn and sometimes that doesn't work either.

Related

Realm Migration Swift

I added a new Class ,newClass, to my Realm file through Realm Studio to allow users to manage an array of items. I also created swift file to manage the new class in XCode.
Since running the app immediately after doing the above, all my data from the firstClass, has disappeared (not a problem the user adds all data in this class on startup, I can repopulate whilst testing the app.)
My app now crashes whenever it reaches any code let realm = try! Realm(). I have commented out or removed references to these to see if it is a localised problem, but it still continuous to crash with the following similar errors depending on the VC it crashes on when during let realm = try! Realm().
schema version 1
Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=1 "Provided schema version 0 is less than last set version 1." UserInfo={NSLocalizedDescription=Provided schema version 0 is less than last set version 1., Error Code=1}: file /Users/UserName/Desktop/AppName/AppName/Custom VC's/AddDataToRealmViewController.swift, line 168
2020-06-27 13:23:10.481817+0100 AppName[4498:173994] Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=1 "Provided schema version 0 is less than last set version 1." UserInfo={NSLocalizedDescription=Provided schema version 0 is less than last set version 1., Error Code=1}: file /Users/UserName/Desktop/AppName/AppName/Custom VC's/AddDataToRealmViewController.swift, line 168
After doing a little bit of reading around, it suggest I need to migrate my realm file to the new schema? Before I attempt this, would this be the correct course of action to take?

Why does a Realm's schema version reset to 0 after a migration?

I'm trying to perform a Realm migration with the following code:
let version = try! schemaVersionAtURL(Realm.Configuration.defaultConfiguration.fileURL!)
let config = Realm.Configuration(
schemaVersion: version + 1,
migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < 1 {
migration.enumerateObjects(ofType: MyObject.className()) { oldObject, newObject in
// Here I transfer existing data to new properties
}
}
})
Realm.Configuration.defaultConfiguration = config
let _ = try! Realm()
The migration seems to work fine, but the next time the app is relaunched, both the current and old schema versions are 0, despite having been set to 1 by the migration that occurred during the first launch.
But the migration is done, so the if condition is true, and the app crashes with a Realm exception caused by trying to perform the migration again.
Can anyone help me understand what I'm missing? If the configuration is setting the schema version to 1 during the migration, why is it 0 the next time the app is relaunched?
The migration seems to work fine, but the next time the app is
relaunched, both the current and old schema versions are 0,
This is caused when you delete the local Realm file and reinstall it, usually occur when you delete and reinstall the application,
Realm handles migrations automatically all it need to know if there was a new version number that would cause the file to rewrite it self with the new rules.
Now for the crashing part, you are using this, an issue with an open stat on github
let version = try! schemaVersionAtURL(Realm.Configuration.defaultConfiguration.fileURL!)
However i agree with this comment.
I guess there's two issues here:
1- It sounds like schemaVersionAtURL() is creating an empty file if given
a URL for a file that doesn't exist, and it obviously shouldn't be
doing that.
2- In Swift schemaVersionAtURL() should be UInt64? and just
return nil if the file doesn't exist rather than throwing
I recommend using plain Int for version rather than getting it from the file,
as it shows in Realm documents, schemaVersion: 1, and increment it manually this will let you always see what version number you are on and when it crashes you know you did something worthy a migration.
Now for the part where you say.
both the current and old schema versions are 0
When you reinstall your application it simply recreate the file with version 0 because the new rules your code implemented to Realm its just simple new file so setting schema version to lower in code would not do pretty much, however this is not recommended because when you go live people will not reinstall the application they will update it, therefore a Realm file is migrated to upper version, however the new users downloading the application with version number 0, so think about it more as a change need to be made rather than an increment number only bigger is better.
Turns out the issue was actually calling Realm before the migration was performed. I'd forgotten a bit of code I had running in willFinishingLaunchingWithOptions that called it.
Lesson Learned: Only the very first call to Realm performs the migration.

Xcode: +CoreDataProperties.swift issue

I'm designing an app which is going well but I had an issue a while ago whereby I had to create a new model for CoreData because I made alterations to the Entities. I'm up to the fourth version and I had another issue with the app and I cleaned it. Now, this is what I'm getting:
The 'deleted' Attribute is set to NSDate
but after I try to build it again I get the following error:
I thought if I made alterations to the Entity Xcode would pick that up and alter any files accordingly! But that doesn't seem to be the case!
I've tried deleting the +CoreDataProperties.swift files and the 'Shopping List' swift file, recreating the 'Shopping List' swift file, under a different class name, and trying to build it again but I get the same error. This tells me its a CoreData issue, not a Swift issue. Obviously I need the attribute as NSDate but I'm not sure where to go from here!
The only way I can get the app to build is to comment out the 'deleted' attribute in the +CoreDataProperties.swift file and it runs fine.
I have the app running on a test iPhone 6 and the last time I made changes to the Entity I lost all the data I entered manually on the phone because of errors. The only way to get the app back up and running was to delete the app off the phone and reinstall it. I seriously don't want to go down that route again because I have nearly 450 various records on the phone.
If I leave the 'deleted' Attribute commented out when its uploaded to the app store, will it fail to upload, and will it fail to work correctly if the upload is successful?
I'd rather sort the issue before trying!
What you need to do is called light weight migrations. In app delegate you need to tell the app to look for the new version and create presistence store
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/// THIS IS THE CODE YOU NEED TO ADD
let container = NSPersistentContainer(name: "NAMEGOESHERE")
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
// End of new code
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
This method worked for me. There are a number of tutorials out there on doing light weight migrations here and there is a stack overflow answer which is one I actually referred to when I had this problem here. By doing migrations your app shall be able to create a new persistance store and in that new store it ll change the attribute of deleted from Bool to NSdate as in the generated managedobject file. Hope this helps

Crash when using deleteRealmIfMigrationNeeded with Realm in Swift

I'm doing the following inside of didFinishLaunchingWithOptions:
let config = Realm.Configuration(
schemaVersion: 0,
deleteRealmIfMigrationNeeded: true
)
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm()
Basically, while developing, I don't want to worry about migrations and just want to clear the database whenever the schema changes. My understanding is that's exactly what deleteRealmIfMigrationNeeded is for.
The problem is that sometimes it crashes while trying to initialize Realm with the following error:
fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=5 "Directory at path '/Users/rock/Library/Developer/CoreSimulator/Devices/D626848E-14D5-47AC-8FFB-9B67D024DEF1/data/Containers/Data/Application/6F71103C-9E10-4131-BED4-D96445FABA52/Documents/default.realm' does not exist."
The default.realm file is getting removed, presumably because of deleteRealmIfMigrationNeeded, but then isn't getting recreated (as I'd expect) when initializing Realm with that last line.
Interestingly, if I manually delete default.realm.lock and then restart the app, it'll work.
Am I doing this wrong? Could this be a bug? (I'm using Realm Swift 2.4.1)
I just came across the same problem and the solution in my case was to turn off the Realm Browser if you have it open.
Cheers!
I discovered that turning off encryption when setting up the Realm will allow you to have the Realm Browser open at the same time.

executeFetchRequest:error: A fetch request must have an entity

I had a project that was working fine. It had "Core Data" checked, and had the data model all set up. I only started adding a couple entities and properties tonight. When I try to run my app now, it won't even load. It just crashes on me.
Here's the error:
'NSInvalidArgumentException', reason: 'executeFetchRequest:error: A fetch request must have an entity.'
I'm really scared because I don't have a backup of this and if I can't get it working I don't know what I'll do. :)
Thanks in advance!
EDIT:
I got fed up with my data, so I just copied a new blank xcdatamodel to my project and I'm going to start fresh. Thanks for the help!
My issue is I didn't use the same name for Entity and Class. Trivial solution to fix it is by giving them the same name.
If you are using MagicalRecored with Swift:
Make sure you use #objc directive in the Swift NSManagedObject subclass to make the class accessible to Objective-C code from the MagicalRecord library
#objc(MyEntity)
class MyEntity: NSManagedObject {
#NSManaged var myAttribute: Int16
}
After searching all over for a solution, what fixed it for me was doing a Clean/Build in Xcode.
Product->Clean, Product->Build, then try running it.
It seemed as if my data got corrupted, so I deleted my data model and the database in the iPhone simulator, and started fresh.
I had the same error.
For me, it is because I have added a new Model Version, but I did not set it as "Current Version". Careless me! To fix, select the xcdatamodel, click Design > Data Model > Set Current Version. The xcdatamodel file will then have a green tick.
Hopes that helps.
Also, make sure that your .xcdatamodeld file is in the "Copy Bundle Resources" phase of your Build Phases.
Here's what fixed it for me:
As I was converting to Swift 3, Xcode was giving me an error when declaring a new NSFetchRequest, saying that it needed a type. After adding the type, I did what anyone else would have assumed; if the request is typed, why specify an entity name? So, I removed it.
It actually was my mistake.
Swift 2.2:
let request = NSFetchRequest(entityName: "MyEntity")
When I first converted to Swift 3:
let request = NSFetchRequest<MyEntity>()
That was giving me an error. I ended up with this:
let request = NSFetchRequest<MyEntity>(entityName: "MyEntity")
And everything works fine. Personally, I'm not sure why it needs to have an entity name specified, if you're typing the request. Maybe they'll update that at some point (I hope)
i found this solution in the apple develper forum and it was exactly my problem!
the solutions is that the context must be defined inside the struct App.
not in the environment parameter
import SwiftUI
#main
struct CoreDataDemoApp: App {
private let context = CoreDataStack.context.
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, context)
}
}
}
Check if,
the entity is present in the xcdatamodel file.
entity name used are same.
If you are using Swift 3 and Core Data's new stack syntax:
var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyAppModel")
container.loadPersistentStores(completionHandler: {
(storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
} else {
print(storeDescription)
}
})
return container
}()
Then you should be using this fetch syntax:
let request: NSFetchRequest<Client> = Client.fetchRequest()
I had this error on the first fetch after app launches when using different variations:
let request: NSFetchRequest<NSFetchRequestResult> = Client.fetchRequest()
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Client")
I did stumble across the same precise error upon taking my first steps into Core Data (and iOS 11 and Swift 4). I started off a book (sixth edition meant to target Swift 4 but presumably including some legacy stuff).
As suggested in the book my code was:
let fetchRequest = NSFetchRequest<ReminderData>()
let entity = ReminderData.entity()
fetchRequest.entity = entity
do {
let rows = try managedObjectContext.fetch(fetchRequest)
} catch {
fatalError("Unresolved error")
}
It turned out that all I got from ReminderData.entity() is nil. Not sure if I did something wrong when setting up the data model or ... Apple's docs say that NSManagedObject.entity() must not be overwritten?
Long story short, the Codegen file ReminderData+CoreDataProperties.swift did include the solution:
#nonobjc public class func fetchRequest() -> NSFetchRequest<ReminderData> {
return NSFetchRequest<ReminderData>(entityName: "ReminderDB")
}
which was all I had to use to end-up with a proper NSFetchRequest, no fiddling with the NSEntityDescription, problem gone!
let fetchRequest = NSFetchRequest<ReminderData>(entityName: "ReminderDB")
do {
let rows = try managedObjectContext.fetch(fetchRequest)
} catch {
fatalError("Unresolved error")
}
I built clean, and that didn't fix it. Then I deleted the app, and that didn't fix it. Then I built clean and deleted the app AT THE SAME TIME, and that fixed it.
Just add the same problem. I copied all my entities. Deleted the data model, recreated an empty one and pasted the entities back into the new data model. Solved my issue.
First I downloaded the app's data through the Organizer (to see what was happening) and noticed that it offered me to save it under a previous project name. This puzzled me. So I exited XCode 4.6.1, deleted the app (and its data) from my iPhone, and came back.
This time I got an error saying Cannot create an NSPersistentStoreCoordinator with a nil model. So I looked into the AppDelegate.m file and changed the URLForResource in the - (NSPersistentStoreCoordinator *) persistentStoreCoodinator method. It was set to the name of my app, and I changed it to 'Model' so as to match the name of my Model.xcdatamodeld.
It's working now.
This happened to me when I was fetching from the wrong database. My application has 3 sqlite databases, and of course 3 ManagedObjectContext instances. Well I was submitting the wrong ManagedObjectContext to a method asking it to query a table that didn't exist in the ManagedObjectContext I submitted. After using the correct ManagedObjectContext, all was good.
I think the original question/problem, and also the issue that most of these answers fixes (just in different ways) is just a real simple one:
Anytime you modify your core data (like adding an entity as you mention), you either have to delete all existing data (if you haven't published your app yet), or add a new version to your model.
Just thought I would post this answer, even though this is an older question, because this answer seems pretty obvious and so far hasn't been discussed in any of the questions or comments I read above.
You can also use setter method from CoraData ... Just do something like this...
On your CustomCoreDataManager.m
import "ObjectiveRecord.h"
call init method like this
(instancetype)init {
self = [super init];
if (self) {
[[CoreDataManager sharedManager] setModelName:#"YourModelName"];
}
return self; }
Hope this helps to someone...
Maybe you are trying to load a Database from a different/the wrong bundle?
For instance from or within a Framework?
I had this issue and solved it by loading the DB from the bundle of the related Framework. And then it all worked fine!!
Swift 4 + MagicalRecord:
let frameworkBundle = Bundle(for: AClassFromTheFramework.self)
let managedObjectModel = NSManagedObjectModel.mergedModel(from: [frameworkBundle])
MagicalRecord.setShouldAutoCreateManagedObjectModel(false)
NSManagedObjectModel.mr_setDefaultManagedObjectModel(managedObjectModel)
MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: "db.sqlite")
And voila !
I faced same issue, actually i was calling MyEnty instead of MyEntity so please re-check what names you have given to your entities and call the same and also check whether you are calling same attributes that you have defined like name
In my case, it was because this dropdown was not set to "Current Product Module" in the Data Model Inspector in Xcode (13.4.1):
Once I set that, it stopped crashing.
Hope this helps!