Originally created by @andriichernenko on GitHub (Nov 25, 2016).
I include .recreateStoreOnModelMismatch in the store options, but it doesn't seem to do what it is supposed to. Application still crashes after I change the model.
The issue seems to be somewhere in this code:
@discardableResultpublicfuncaddStorageAndWait<T:LocalStorage>(_storage:T)throws->T{// ...do{// ... do{// ...}catchleterrorasNSErrorwherestorage.localStorageOptions.contains(.recreateStoreOnModelMismatch)&&error.isCoreDataMigrationError{letmetadata=tryNSPersistentStoreCoordinator.metadataForPersistentStore(ofType:type(of:storage).storeType,at:fileURL,options:storeOptions)// self.model[metadata] returns nil, so storage.eraseStorageAndWait is not called_=tryself.model[metadata].flatMap(storage.eraseStorageAndWait)// another attempt to create storage throws exception which crashes the app_=tryself.createPersistentStoreFromStorage(storage,finalURL:fileURL,finalStoreOptions:storeOptions)returnstorage}}catch{// ...}}
As I understand, self.model[metadata] subscript tries to find the model by entity hashes (NSStoreModelVersionHashesKey) which is suspicious (I thought these hashes are different by definition when models are different?):
@nonobjcinternalsubscript(metadata:[String:Any])->NSManagedObjectModel?{guardletmodelHashes=metadata[NSStoreModelVersionHashesKey]as?[String:Data]else{returnnil}formodelVersioninself.modelVersions??[]{// suspicious comparison, can we use entity hashes here?ifletversionModel=self[modelVersion],modelHashes==versionModel.entityVersionHashesByName{returnversionModel}}returnnil}
Originally created by @andriichernenko on GitHub (Nov 25, 2016).
I include `.recreateStoreOnModelMismatch` in the store options, but it doesn't seem to do what it is supposed to. Application still crashes after I change the model.
The issue seems to be somewhere in this code:
```swift
@discardableResult
public func addStorageAndWait<T: LocalStorage>(_ storage: T) throws -> T {
// ...
do {
// ...
do {
// ...
}
catch let error as NSError where storage.localStorageOptions.contains(.recreateStoreOnModelMismatch) && error.isCoreDataMigrationError {
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
ofType: type(of: storage).storeType,
at: fileURL,
options: storeOptions
)
// self.model[metadata] returns nil, so storage.eraseStorageAndWait is not called
_ = try self.model[metadata].flatMap(storage.eraseStorageAndWait)
// another attempt to create storage throws exception which crashes the app
_ = try self.createPersistentStoreFromStorage(
storage,
finalURL: fileURL,
finalStoreOptions: storeOptions
)
return storage
}
}
catch {
// ...
}
}
```
As I understand, `self.model[metadata]` subscript tries to find the model by entity hashes (`NSStoreModelVersionHashesKey`) which is suspicious (I thought these hashes are different by definition when models are different?):
```swift
@nonobjc
internal subscript(metadata: [String: Any]) -> NSManagedObjectModel? {
guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : Data] else {
return nil
}
for modelVersion in self.modelVersions ?? [] {
// suspicious comparison, can we use entity hashes here?
if let versionModel = self[modelVersion], modelHashes == versionModel.entityVersionHashesByName {
return versionModel
}
}
return nil
}
```
adam
added the fixed label 2025-12-29 15:24:42 +01:00
// self.model[metadata] returns nil, so storage.eraseStorageAndWait is not called
I completely missed this case, thanks so much! Will try to push a fix within the day
@JohnEstropia commented on GitHub (Nov 26, 2016):
> // self.model[metadata] returns nil, so storage.eraseStorageAndWait is not called
I completely missed this case, thanks so much! Will try to push a fix within the day
I thought these hashes are different by definition when models are different?
The original assumption is that all previous model versions are bundled in the app (or theres no way we can infer how to migrate).
I missed the case where we change our model while debugging, which was what this flag was originally designed for :(
@JohnEstropia commented on GitHub (Nov 26, 2016):
Just to note:
> I thought these hashes are different by definition when models are different?
The original assumption is that all previous model versions are bundled in the app (or theres no way we can infer how to migrate).
I missed the case where we change our model while debugging, which was what this flag was originally designed for :(
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @andriichernenko on GitHub (Nov 25, 2016).
I include
.recreateStoreOnModelMismatchin the store options, but it doesn't seem to do what it is supposed to. Application still crashes after I change the model.The issue seems to be somewhere in this code:
As I understand,
self.model[metadata]subscript tries to find the model by entity hashes (NSStoreModelVersionHashesKey) which is suspicious (I thought these hashes are different by definition when models are different?):@JohnEstropia commented on GitHub (Nov 26, 2016):
I completely missed this case, thanks so much! Will try to push a fix within the day
@JohnEstropia commented on GitHub (Nov 26, 2016):
Just to note:
The original assumption is that all previous model versions are bundled in the app (or theres no way we can infer how to migrate).
I missed the case where we change our model while debugging, which was what this flag was originally designed for :(
@JohnEstropia commented on GitHub (Nov 26, 2016):
@deville I updated the swift3_develop branch. Try it out :)
@andriichernenko commented on GitHub (Nov 26, 2016):
The problem has been resolved, thank you!