Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreData: annotation: Failed to load optimized model at path (Xcode 11 -> iOS 12)

When building and running a Core Data project (created with Xcode 10) using Xcode 11 (beta 3) on an iOS 12 device, I get the warning:

CoreData: annotation: Failed to load optimized model at path '/var/containers/Bundle/Application/7908B3F7-66BC-4931-A578-6A740CBFB37D/TestOMO.app/TestOMO.momd/TestOMO.omo'

There is no warning if

  • I build and run it using Xcode 10 on iOS 12 device
  • I build and run it using Xcode 11 on iOS 13 device

My app seems to work fine and there are no crashes, so I am not sure how seriously to take this warning. Nonetheless I would surely prefer to get rid of it.

There are many posts related to this Core Data annotation, but most are either related to Google Maps or are unanswered.

I have created a new project to eliminate other causes for the issue related to my own project and to make it easy to reproduce as follows:

  1. Create a new project using Xcode 10 (Single View App, Use Core Data)
  2. In AppDelegate.swift, add print ("psc = (persistentContainer)") to func application(_ , didFinishLaunchingWithOptions:) (just to force lazy var initialisation)
  3. Build and run on an iOS12 device: no issues
  4. Open the same project in Xcode 11, build and run on an iOS13 device: no issues
  5. Sill in Xcode 11, build and run on an iOS12 device: you will get the warning quoted above

Cleaning the build folder or deleting derived data is of no help.

like image 942
mmklug Avatar asked Jul 05 '19 15:07

mmklug


2 Answers

I was able to solve the issue thanks to the hint in @ChaitanyaKhurana's comment above.

Here is the swift code I have implemented, replacing the original single line

let container = NSPersistentContainer(name: "ModelName")

Part of the code is needed to retrieve the model version string (from the .plist file located in the .momd package) in order to avoid having to update the code each time there is a new model version.

Please also note that the new/alternative code only executes on iOS versions prior to 13.0 as there is not issue on iOS 13.

let modelName = "ModelName"

var container: NSPersistentContainer!

if #available(iOS 13.0, *) {
    container = NSPersistentContainer(name: modelName)
} else {
    var modelURL = Bundle(for: type(of: self)).url(forResource: modelName, withExtension: "momd")!
    let versionInfoURL = modelURL.appendingPathComponent("VersionInfo.plist")
    if let versionInfoNSDictionary = NSDictionary(contentsOf: versionInfoURL),
        let version = versionInfoNSDictionary.object(forKey: "NSManagedObjectModel_CurrentVersionName") as? String {
        modelURL.appendPathComponent("\(version).mom")
        let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL)
        container = NSPersistentContainer(name: modelName, managedObjectModel: managedObjectModel!)
    } else {
        //fall back solution; runs fine despite "Failed to load optimized model" warning
        container = NSPersistentContainer(name: modelName)
    }
}
like image 113
mmklug Avatar answered Nov 19 '22 14:11

mmklug


Since older code can often be in Objective C, here's an ObjC version (this is sourced on the answer from @Lobo):

- (NSPersistentContainer *)samplePersistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {

        if (_persistentContainer == nil) {

            NSString *modelName = @"ModelName";

            if (@available(iOS 13, *)) {

                _persistentContainer = [NSPersistentContainer persistentContainerWithName: modelName];
                [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                    if (error != nil) {
                        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                        abort();
                    }
                }];

            } else {

                NSString *modelURLPath = [[NSBundle mainBundle] pathForResource: modelName ofType: @"momd"];

                NSURL *modelURL = [NSURL fileURLWithPath: modelURLPath];

                NSURL *versionInfoURL = [modelURL URLByAppendingPathComponent: @"VersionInfo.plist"];

                NSDictionary *versionInfoNSDictionary = [NSDictionary dictionaryWithContentsOfURL: versionInfoURL];

                NSString *version = versionInfoNSDictionary[@"NSManagedObjectModel_CurrentVersionName"];

                modelURL = [modelURL URLByAppendingPathComponent:[NSString stringWithFormat: @"%@.mom", version]];

                NSManagedObjectModel *mod = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL];

                _persistentContainer = [NSPersistentContainer persistentContainerWithName: modelName managedObjectModel: mod];
            }
        }
    }

    return _persistentContainer;
}
like image 1
bauerMusic Avatar answered Nov 19 '22 14:11

bauerMusic