Подтвердить что ты не робот

IPhone Core Data Lightweight Migration Cocoa error 134130: Не удается найти модель для хранилища источников

Люди,

Легкая миграция не работает для меня 100% времени в этой строке:

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]

с ошибкой:

Error: Error Domain=NSCocoaErrorDomain Code=134130 UserInfo=0x4fbff20 "Operation could not be completed. (Cocoa error 134130.)"
"Can't find model for source store";

Вот мой контекст, модель и постоянное хранилище управляемых объектов:

- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }

    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"]];

    NSError *error;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    // Allow inferred migration from the original version of the application.
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        NSLog(@"Error: %@",error);
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

У меня есть две версии моей модели в моем проекте: версия 4 и версия 5. Если я установлю свою версию 4 по умолчанию, она отлично работает. Если я выберу "Дизайн → Модель данных → Добавить версию модели" (как описано этот пост), внесите изменения, Design → Data Model → Set Current Версия, сборка и запуск, она потерпит неудачу с вышеупомянутой ошибкой "Невозможно найти модель для источника". Установите модель обратно в версию 4, без проблем, addPersistentStoreWithType. В качестве альтернативы, если я добавлю версию модели и не вношу никаких изменений, просто перейдите от версии 4 к 5 без добавления каких-либо новых полей, никаких проблем. Если я попытаюсь перейти от 5 до 6, вышеназванная ошибка.

Этот код не работает как на Simulator, так и на телефоне. Я прочитал несколько рецептов, призывающих удалить и переустановить приложение, которое работает как для Simulator, так и для телефона, но я боюсь, что когда я выпущу его для реальных пользователей, он сломает мою установленную базу, так как они не смогут удалить и переустановить - App Store будет автоматически обновлять их.

Этот код работал в предыдущих выпусках без каких-либо изменений с моей стороны - отсюда моя способность сделать все до версии 4. Недавно я обновился до создания XCode 3.2.3 для iOS4, что может иметь какое-то отношение к этому,

Есть ли у кого-нибудь еще этот вопрос внезапно сейчас, как я? Кто-нибудь сумел обойти это? Спасибо.

PS. Для гуглеров, которые спотыкаются на этой странице, вот все соответствующие страницы, которые вы можете рассмотреть, ниже. К сожалению, ни одна из них не решила мою проблему.

UPDATE

Хотя это не является реальным исправлением, он избегает сценария сбойного клиента: просто удалите файл базы данных:

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {



    // Delete file
    if ([[NSFileManager defaultManager] fileExistsAtPath:storeUrl.path]) {
        if (![[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) 
    {
        // Handle the error.
        NSLog(@"Error: %@",error);
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();

    }
}    

ОБНОВЛЕНИЕ 2

Вот что происходит, когда я проверяю VersionInfo.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>NSManagedObjectModel_CurrentVersionName</key>
        <string>Profile 5</string>
        <key>NSManagedObjectModel_VersionHashes</key>
        <dict>
                <key>Profile</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        ZIICGgMBreuldkPXgXUhJwKamgwJzESM5FRTOUskomw=
                        </data>
                </dict>
                <key>Profile 2</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        tEB7HrETWOSUuoeDonJKLXzsxixv8ALHOoASQDUIZMA=
                        </data>
                </dict>
                <key>Profile 3</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        qyXOJyKkfQ8hdt9gcdFs7SxKmZ1JYrsXvKbtFQTTna8=
                        </data>
                </dict>
                <key>Profile 4</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
                        </data>
                </dict>
                <key>Profile 5</key>
                <dict>
                        <key>Profile</key>
                        <data>
                        V4PyRK1ezj3xK1QFRCTVzGOqyJhEb7FRMzglrTsP0cI=
                        </data>
                </dict>
        </dict>
</dict>
</plist>

Вот код, который я написал для проверки моей модели (обратите внимание, что мне нужно было выйти и добавить кодировщик base64, поскольку это то, что находится в файле VersionInfo.plist)

if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {


    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
    NSLog(@"%@",storeMeta);
    id someObj = [[storeMeta objectForKey:@"NSStoreModelVersionHashes"] objectForKey:@"Profile"];
    NSLog(@"%@",someObj);
    NSLog(@"%@",[NSString base64StringFromData:someObj length:[someObj length]]);

И вот вывод отладки:

{
    NSPersistenceFrameworkVersion = 310;
    NSStoreModelVersionHashes =     {
        Profile = <97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>;
        SerializedMessage = <4530863c d943479a edfb4dfb 5059c28d d6137dc4 d1153d36 ed52be49 11074f13>;
    };
    NSStoreModelVersionHashesVersion = 3;
    NSStoreModelVersionIdentifiers =     (
    );
    NSStoreType = SQLite;
    NSStoreUUID = "823FD306-696F-4A0F-8311-2792825DC66E";
    "_NSAutoVacuumLevel" = 2;
}

<97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=

Как вы можете видеть, последняя строка, начинающаяся с "ly", соответствует профилю 4 в VersionInfo.plist... поэтому я не вижу причин, по которым он должен быть неудачным. Любые другие идеи?

4b9b3361

Ответ 1

Люди,

Для записи я полностью прекратил использование основных данных. Мой код был сложным и, по вышеперечисленным вопросам, был ненадежным. Я использую SQLLite прямо сейчас, и я более счастлив. Я не могу рекомендовать использование Core Data в любом сценарии.

Ответ 2

Я прочитал несколько рецептов для удаления и повторной установки приложения, который работает как для Simulator, так и для Телефон, но я боюсь, что когда я отпустите это для реальных пользователей, это будет сломайте мою установленную базу, так как они не удастся удалить и переустановить.

Это проблема, вызванная тем, что Xcode не удаляет старые файлы momc из simulator/dev-device при изменении файла модели, например. изменение имени. Остается старый файл, который вызывает путаницу. Это то, что вы видите только во время разработки, потому что это артефакт того, как Xcode манипулирует набором приложений, не переустанавливая его каждый раз, как это должно произойти с версией выпуска.

Вы можете подтвердить это регистрацию возврата:

[[NSBundle mainBundle] URLsForResourcesWithExtension:@"momc"subdirectory:nil];

..., который должен показать вам все скомпилированные файлы модели в комплекте приложений

Плохая практика заключается в том, чтобы полагаться на миграцию во время разработки, потому что очень редко происходит переход к миграции, если вы вносите изменения в модель и сохраняете. Вы должны использовать миграцию только после того, как весь код забит. Я бы также рекомендовал регенерировать ваш магазин с нуля каждый раз, когда вы запускаете. Это легко создать мусор в магазине, изменив модель.

Ответ 3

Я прочитал ваш обновленный вопрос. Это становится довольно грязным с версиями модели.

Вы должны попробовать и проверить версию модели, о которой уже спрашивает существующий магазин, и попытаться перечислить все доступные модели в комплекте приложений во время выполнения.


Я смотрю в каталоге моделей моих приложений

NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"MyModel" ofType:@"momd"];

Я не уверен, что разработчики обычно это делают, но я сохраняю свои версии моделей с разными именами.. так что я там:

  • VersionInfo.plist
  • MyModel.mom
  • MyModel2.mom

Хеши версии, перечисленные в VersionInfo.plist, должны помочь вам устранить неполадки. Найдите хеш-версию, требуемую существующим постоянным хранилищем, и посмотрите, можете ли вы найти ее в хэшах версий, перечисленных в VersionInfo.plist.

На самом деле, я не вижу способа написать код, который будет запрашивать постоянное хранилище, что такое хэш-версия сущности. Кажется, что NSPersistentStoreCoordinator или NSMigrationManger делают это конфиденциально. то есть они проверяют постоянные версии сущности хранилища на модели, в которую загружен магазин.


Был еще один быстрый взгляд, и он доступен в метаданных магазина. Приятно и легко!

NSError *error;
NSURL *storeURL = [NSURL fileURLWithPath:[[self class] storePath]];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeURL error:&error];

И глядя в storeMeta Я получаю ключ с

<CFString 0x7328050 [0x2724380]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x7328340 [0x2724380]>{type = immutable dict, count = 5,
entries =>
    0 : <CFString 0x7328110 [0x2724380]>{contents = "MyEntityNameOne"} = <CFData 0x73281b0 [0x2724380]>{length = 32, capacity = 32, bytes = 0x143325cf121239ce156af2e2a1aad7d9 ... 976977fdf29fc013}
    1 : <CFString 0x7328130 [0x2724380]>{contents = "MyEntityNameTwo"} = <CFData 0x7328200 [0x2724380]>{length = 32, capacity = 32, bytes = 0x0ca6ecf1283d12bd3ca82af39b6b9f5d ... 149dd39a591e0c4d}
    ...    }

Должно быть легко перебирать словарь NSStoreModelVersionHashes и записывать хеширование версии, которое требуется вашему магазину.

Вручную сопоставьте это с теми, которые доступны в VersionInfo.plist, и посмотрите, что отсутствует. Возможно, нет ни одной модели, которая содержит все необходимые версии сущностей в вашем существующем постоянном хранилище. Это может произойти из-за (случайных?) Изменений в модели до или после настройки новой версии модели?

Ответ 4

У меня была точная проблема с esilver и нашел этот вопрос через Google. Однако исправление, которое сработало для меня, не было нигде в SO (что я знаю), так вот:

Если в вашем комплекте есть несколько копий ваших файлов *.mom (скомпилированные объектные модели), Core Data может запутаться при попытке выполнить миграцию от вашего имени.

Наша проблема заключалась в том, что каждый отдельный файл модели (Data.xcdatamodel, Data_V1.xcdatamodel, Data_V2.xcdatamodel и т.д.) был не только внутри каталога xcdatamodeld/ (который был включен как что-то для компиляции в процессе сборки) но также каждый файл также был включен в список "Источники компиляции".

Это означает, что полученный пакет имел два набора файлов *.mom: один внутри xcdatamodeld/ и один на верхнем уровне. Я думаю, что Core Data очень сильно запутался и привел к этой ошибке. Удаление каждого файла xcdatamodel из "источников компиляции" и оставление каталога xcdatamodeld решило проблему для нас (например, снова и снова запускалось автоматическое обновление). Надеюсь, это поможет!

Ответ 5

Ну, в моем случае точно то же самое происходило, и я был на iOS 7, и эта проблема прикрутила мою голову хотя бы на неделю, а затем, наконец, нашла решение, которое работает для меня , Чтобы сделать это, вы должны добавить дополнительное значение в опции, которые используются для добавления PersistentStore, а затем вы идете (я не уверен в другой версии iOS, но да, это определенно будет работать на iOS 7).

-(NSManagedObjectModel *)managedObjectModel
{
    if (managedObjectModel != nil)
    {
        return managedObjectModel;
    }
    managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    return managedObjectModel;
}

-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
 {

   if (persistentStoreCoordinator != nil)
   {
       return persistentStoreCoordinator;
   }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ABC.sqlite"];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] ini   tWithManagedObjectModel:[self managedObjectModel]];

//Creating Lightweight migration.
    NSDictionary *options =
    @{
      NSMigratePersistentStoresAutomaticallyOption:@YES
      ,NSInferMappingModelAutomaticallyOption:@YES
      ,NSSQLitePragmasOption: @{@"journal_mode": @"DELETE"}
     };


   if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
       abort();
    }
return persistentStoreCoordinator;
}