RealmSwift: Realm at path already opened with different schema version - ios

I've recently created a new branch and attempted refactoring much of my code to give Realm a shot over CoreData. But so far I haven't had any luck getting my code to run.
First, an exception is thrown in shared_realm.cpp. The line of code that throws the error is:
if (realm->config().schema_version != config.schema_version && config.schema_version != ObjectStore::NotVersioned) {
throw MismatchedConfigException("Realm at path already opened with different schema version.");
}
If I skip over this exception, it catches on the second line of code in the following:
class func getAllCategories() -> Results<Category> {
let realm = try! Realm()
let categories = realm.objects(Category)
return categories
}
And throws this error message:
fatal error: 'try!' expression unexpectedly raised an error: Error
Domain=io.realm Code=1 "Realm at path already opened with different
schema version." UserInfo={NSLocalizedDescription=Realm at path
already opened with different schema version., Error Code=1}
I am completely new to Realm, so any help is appreciated. My understanding from the documentation is that Realm() is the proper way to access the default database, which is fine for my purposes at the moment. At first I thought that perhaps a Realm had to be passed around, but I see from online examples that this doesn't appear to be the case.
I have cleaned, changed simulators, and even updated Xcode. I also attempted to comment this line of code back in:
// FIXME - enable schema comparison
/*if (realm->config().schema != config.schema) {
throw MismatchedConfigException("Realm at path already opened with different schema");
}*/
to no avail. Feeling quite lost, so any direction is appreciated.

The schema version for a path can't be changed after it has been opened, so you'll need to change the schema before calling the path with setSchemaVersion.
setSchemaVersion(1, realmPath: Realm.defaultPath) { (migration, oldSchemaVersion) -> Void in
if oldSchemaVersion < 1 {
migration.enumerate(Category.className(), { (oldObject, newObject) -> Void in
let constant = oldObject!["constant"] as! String
newObject!["constant"] = constant
})
}
}

You might be running into this problem, because you changed the schema after you already built the app once (just a guess, you can confirm this by deleting the app and rebuilding it, which also clears the existing realm database.)
If that is indeed the problem, you should look into
https://realm.io/docs/swift/latest/#migrations
which outlines the recommended way to fix this issue.

For me the issue was that I added a new field as a String like this :
schema.get("RealmCompany").addField("ctype", String.class);
When I declared it in the model class as an Integer.
I had to do :
if (oldVersion == 7) {
Log.i(TAG, "migrate: " + 7);
schema.get("RealmCompany").removeField("ctype");
schema.get("RealmCompany").addField("ctype", Integer.class);
}

Related

An error occurring during Core Data persistent store migration in iOS 13

After updating XCode to version 11 I added a new model version to Core Data and in new version I added a new attribute to an Entity. Made the new version active and added the new property to managed object file.
After releasing this version to the users it started to crash with the following message: "The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store." and "duplicate column name ZNEWCOLUMN". Until now I made a lot of changes to the Core Data model and migration always worked.
This crash appears only on iOS 13!
This is how I load Core Data:
lazy var managedObjectContext: NSManagedObjectContext = {
return self.persistentContainer.viewContext
}()
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.
*/
let container = NSPersistentContainer(name: "MyModel")
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)")
}
})
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions.append(description)
return container
}()
Any help would be appreciated.
The same thing is happening to me, lightweight migration at iOS 12 was right at real device and Simulator but at iOS 13 fail with the next log result:
SQLite error code:1, 'duplicate column name: ZNAME_OF_THE_COLUMN .... Error Domain
= NSCocoaErrorDomain Code = 134110 "An error occurred during persistent storage migration."
I load data like #iOS Dev post.
I check the xxxx.sqlite database file in the emulator path before and after the migration and there were no columns with those new same names.
To know the route of the *.sqlite in emulator you have to put a breakpoint and when it is stopped put in the console po NSHomeDirectory().
Then go to Finder window, tap the keys Control + Command + G and paste the route. Yo can handle it (for example) with DB Browser for SQLite program, it´s free.
After a long search I have seen what has happened to some people but I have not seen any solution.
Mine was:
Select the actual *.xcdatamodel.
Select Editor > Add Model Version.
Provide a version name based on the previous model (like XxxxxxV2.xcdatamodel).
Click on this new version model NewV2.xcdatamodel.
Select this new version as Current on Properties at right hand of IDE.
Make your changes at DDBB.
Run app and will work fine.
I did tests overriding app (with new values) and it was fine.
I hope this may help.
If you want to edit the descriptions, you need to do so before you load the stores (and I have no idea what appending a new description would do):
container.persistentStoreDescriptions.forEach { storeDesc in
storeDesc.shouldMigrateStoreAutomatically = true
storeDesc.shouldInferMappingModelAutomatically = true
}
container.loadPersistentStores { [unowned self] (storeDesc, error) in
if let error = error {
// handle your error, do not fatalError! even a message that something is wrong can be helpful
return
}
// do any additional work on your view context, etc.
}
If your problem is reproduceable, you should look at the error that's being returned and look for something called ZNEWCOLUMN (though this sounds like a temporary default name?) This nomenclature is the raw column name in the SQL database though, so it's likely the migrator is attempting to add this new column and failing.
Try turning on SQL debugging in your scheme's Arguments:
-com.apple.CoreData.SQLDebug 1
Try logging into the raw SQL database (the above will give you the raw path if you're on the simulator). Try rolling back to the previous data model on a previous OS and then just upgrading to 13.
Sounds like you have some duplicate column somewhere so these are just some ideas to find out where it is.

initiaize object of AGSGeodatabase with file path is returning "File not found

I want to post this question on esri community, but I was not able to login there.
I created the offline geo database and showing the layers from it to the map.
My issue is when i download the geoDatabse and show the data from it is working fine for the first time.
But when I restart the app and create the AGSGeodatabase object from path then the "self.generatedGeodatabase.load" function gives error
Error Domain=com.esri.arcgis.runtime.error Code=14 "File not found" UserInfo={NSLocalizedFailureReason=, NSLocalizedDescription=File not found, Additional Message=}
my created url is :-
file:///var/mobile/Containers/Data/Application/60CF7AE1-2DE1-4FA0-805A-6140D4829E89/Documents/GeoDatabase/2018-05-134T18:29:01+0530.geodatabase
and I'm creating object is like this :-
if let geoDatabasePath = URL(string: SettingsManager.geoDatabasePath) {
self.generatedGeodatabase = AGSGeodatabase(fileURL: geoDatabasePath)
self.displayLayersFromGeodatabase()
}
and error is coming when this function runs:-
self.generatedGeodatabase.load(completion: { [weak self] (error:Error?) -> Void in
if let error = error {
print(error)
}
})
Previously I was just saving the path of the geoDatabse to preference (when creating the geoDatabse) and app is not detecting the geoDatabse at that location when I restart the app even the file is there.
The solution to this problem I find is to detect the geoDatabse path at runtime and create path using FileManager. Then it works.

Fatal Error :Can't open realm

I am working on IOS. I am using realm database in the frontend. It was working fine until I made some changes to the realm model and all files related to it. I just added one field to these files.
Now I am getting an error "Fatal error: Can't open realm" in the following code
fileprivate func getRealm() -> Realm {
// get default configuration realm
do {
return try Realm()
} catch {
Swift.fatalError("Can't open realm") //Fatal Error :Can't open realm
}
}
Can anyone tell what might be the possible causes for this error.
Thanks in advance.
If you made changes to the realm model, you need to increase your schema version and you may or may need to provide a migration block. See the official documentation for details.
// Inside your [AppDelegate didFinishLaunchingWithOptions:]
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
config.schemaVersion = 1;
// Set the block which will be called automatically when opening a Realm with a
// schema version lower than the one set above
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// 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
}
};
// Tell Realm to use this new configuration object for the default Realm
[RLMRealmConfiguration setDefaultConfiguration:config];
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
[RLMRealm defaultRealm];
The above issue is caused due to inconsistency in the Realm database. I changed the structure of the model by adding one field. So, the model was having 10 fields but the realm database in my app was having 9 fields, as the app was built before the changes.
I solved the issue by just reinstalling the app which regenerated the realm database in the phone, thereby having a consistent model and database.
The above workaround might be good if your app is yet to be live. But, if your app is already being used by other users, then they will have to reinstall the app on update, which might result in bad user experience for the user.
Ideally, you should be writing a migration block for the new changes.
Hope, this is clear to all.

Error initialize AZSCloudStorageAccount Swift 3

I tried link to my account with this code
let storageAccount : AZSCloudStorageAccount;
try! storageAccount = AZSCloudStorageAccount(fromConnectionString: config.getAzureConnection())
let blobClient = storageAccount.getBlobClient()
var container : AZSCloudBlobContainer = (blobClient?.containerReference(fromName: config.getContainer()))!
the "config.getAzureConnection()" contains the right path because i used the same for android app.
In this line try! storageAccount = AZSCloudStorageAccount(fromConnectionString: config.getAzureConnection()) the app crash without error, only (lldb) .
Can someone help me.
Does your error look like this?
fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.Microsoft.AzureStorage.ErrorDomain Code=1 "(null)": file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182
(lldb)
Code=1 is AZSEInvalidArgument, which means that your connection string is invalid. I am a bit confused why you said "the right path", since fromConnectionString takes the string directly, not the path to a file. To see an example of what a correct connection string looks like, please refer to the Getting Started Guide. Basically it looks like this:
"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here"
We will document the error codes properly very soon. Sorry for the confusion!
the app crash without error, only (lldb) .
I am sorry for that SWIFT blob client haven't provide error-handling code whatsoever currently. I will provide some clues to track your issue based on your code.
Before building the storage code, make one change in the project. Go to 'Azure Storage Client Library' -> Build Settings, search for the "Defines Module" setting, and change it to 'YES'.
Please check whether the issue is caused by bad network connection.
You could get error code of this issue by putting your code in a do-catch code block.
do {
//put your code here
} catch let error as NSError {
print("Error code = %ld, error domain = %#, error userinfo = %#", error.code, error.domain, error.userInfo);
}
The SWIFT blob sample has been tested and work well targeting iOS 9.0 and using XCode 7. If you have a different setup, the sample may not run properly. I suggest you use Blob Storage REST API as a workaround.

iOS Realm readOnly causes empty result

I have a little problem with realm setting readOnly to true in the configuration. I am using Swift but I am using the normal Realm.framework ... Maybe this causes the error but I don't think so. (I am using it because I don't want to refactor my whole code...)
Here is an example of what I am talking about.
I tried this:
if let path = NSBundle.mainBundle().pathForResource("database", ofType: "realm")
{
//Alternative: or move the file from the app bundle into a writable location
var config = RLMRealmConfiguration()
config.path = path
config.readOnly = true
do {
try self.realm = RLMRealm(configuration:config)
} catch {
print("ERROR")
}
I also tried this:
if let path = NSBundle.mainBundle().pathForResource("database", ofType: "realm")
{
//Alternative: or move the file from the app bundle into a writable location
var config = RLMRealmConfiguration()
config.path = path
config.readOnly = true
RLMRealmConfiguration.setDefaultConfiguration(config)
do {
try self.realm = RLMRealm(configuration: RLMRealmConfiguration.defaultConfiguration())
} catch {
print("ERROR")
}
Both of them fail every time. (Printing: "Error") I figured out that the problem is that readOnly is set to true. I got both snippets working by setting readOnly to false.
Do you have any idea how to fix this issue?
I printed the Error and it is:
Error Domain=io.realm Code=2 "Unable to open a realm at path
'/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm'"
UserInfo={NSFilePath=/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm,
NSLocalizedDescription=Unable to open a realm at path
'/Users/UserName/Library/Developer/CoreSimulator/Devices/NR/data/Containers/Bundle/Application/NR/AppName.app/database.realm',
Error Code=2}
Okay guys I have no idea what happened but it works now.
I made a sample project with the database of their database and an object for their database and tried my code and it worked. (Both of them)
This confused me pretty much and I thought maybe my database is damaged or the object is wrong. I replaced their database in the sample project with my database and used my object and surprise it worked...
So I just deleted my database in my normal project (as I did 1000 times before) and added it again. I just put it on the top of my project structure and tried it again and it is working now...

Resources