Ответ 1
Вам нужно перетащить файл xcdatamodeld и отбросить его на этапе сборки. Скомпилируйте источники для целей, которые используют структуру. Затем, когда цель запускает свой [NSBundle mainBundle], будет содержать модель (файл momd).
Я пытаюсь перенести определенную часть одного из моих приложений в фреймворк, чтобы я мог использовать его в самом приложении и в одном из этих новых виджетов iOS 8. Эта часть является той, которая обрабатывает все мои данные в Core Data. Это довольно прямо вперед, чтобы переместить все и получить к нему доступ. У меня просто возникают проблемы с доступом к моему файлу momd
.
При создании NSManagedObjectModel
я по-прежнему пытаюсь загрузить momd
, как показано в шаблонах кода Apple:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
К сожалению, modelURL
остается nil
и, таким образом, MyApp
сбой при доступе к стеку Core Data с этой ошибкой:
2014-08-01 22:39:56.885 MyApp[81375:7417914] Cannot create an NSPersistentStoreCoordinator with a nil model
2014-08-01 22:39:56.903 MyApp[81375:7417914] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'
Итак, какой правильный способ сделать это при работе внутри фреймворка с Core Data?
Вам нужно перетащить файл xcdatamodeld и отбросить его на этапе сборки. Скомпилируйте источники для целей, которые используют структуру. Затем, когда цель запускает свой [NSBundle mainBundle], будет содержать модель (файл momd).
Я немного опаздываю на проблему с пламя, но, надеюсь, это помогает любому другому, кто блуждает. Это можно заставить работать без необходимости выполнять script -fu для копирования ресурсов вокруг!
По умолчанию шаблон Apple Core Data дает вам примерно следующее:
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
Это загрузит ваши ресурсы Core Data из основного пакета. Главное здесь: если модель Core Data загружена в структуру, файл .momd находится в этом пакете структуры. Поэтому вместо этого мы просто делаем это:
lazy var managedObjectModel: NSManagedObjectModel = {
let sexyFrameworkBundleIdentifier = "com.heybaby.xxx"
let customKitBundle = NSBundle(identifier: sexyFrameworkBundleIdentifier)!
let modelURL = customKitBundle.URLForResource("MyCuteCoreDataModel", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
Это должно заставить вас работать и работать.
Кредит: https://www.andrewcbancroft.com/2015/08/25/sharing-a-core-data-model-with-a-swift-framework/
@Рич Сантос был почти там. Я думаю, вам просто нужно сделать это скорее "мамой", чем "мамдом", и тогда она будет работать.
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle(forClass: self.dynamicType.self).URLForResource(self.dataModelName, withExtension: "mom")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
Возможно, я немного опоздаю с ответом на это, но вот что решило мою проблему:
С моей картой я поставляю также пакет с ресурсами, такими как изображения и другие вещи. Ввод файла xcdatamodeld там не дал ничего, поскольку этот файл создается с проектом, и в результате вы получаете папку momd в своем комплекте приложений (чего фактически не хватает в наш случай).. Я создал другую цель, а не фреймворк, но приложение, построил ее и скопировал momd из своего пакета приложений в свой отдельный пакет в проекте (тот, который идет с фреймворком). После этого вам просто нужно изменить URL-адрес ресурса из основного пакета в новый:
// ...
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"separate_bundle" ofType:@"bundle"];
NSURL *modelURL = [[NSBundle bundleWithPath:bundlePath] URLForResource:@"your_model" withExtension:@"momd"];
// ...
Работал хорошо для меня. Единственное, что я знаю, это App Store Review, которого я еще не понял. Поэтому, если вы нашли лучшее решение, поделитесь им.
ИЗМЕНИТЬ
Нашел лучшее решение. Вы можете самостоятельно построить модель. Из Руководство по программированию основных данных:
Модель данных - это ресурс развертывания. В дополнение к деталям объекты и свойства в модели, модель, которую вы создаете в Xcode содержит информацию о диаграмме - ее расположение, цвета элементов, и так далее. Эта последняя информация не требуется во время выполнения. Модель файл скомпилирован с использованием компилятора модели momc для удаления постороннюю информацию и загрузку ресурса во время выполнения насколько это возможно. Исходный каталог xcdatamodeld скомпилирован в директорию развертывания momd, а файл источника xcdatamodel скомпилирован в файл развертывания мамы.
momc находится в /Developer/usr/bin/. Если вы хотите использовать его в своем собственные скрипты сборки, его использование - источник источника momc, где источник - путь к модели Core Data для компиляции, а назначение - путь выхода.
В разделе "/Developer/usr/bin/" они означают "/Applications/Xcode.app/Developer/usr/bin/"
Вы можете добавить script в свою целевую схему и скомпилировать это автоматически перед каждой сборкой (или после, не думайте, что это важно). Это в случае, если вы измените модель во время разработки.
Что-то вроде этого:
mkdir -p "${BUILT_PRODUCTS_DIR}/your_model_name.momd"
momc "${SRCROOT}/your_model_path/your_model_name.xcdatamodeld" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/your_bundle_name.bundle/your_model_name.momd"
Ресурс модели больше не доступен через mainBundle
, вам нужно использовать bundleForClass:
следующим образом:
NSURL *modelURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MyApp" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Я предполагаю, что вам нужна только модель данных.
Если это так, я считаю, что следующий метод является наиболее успешным методом копирования в файле модели данных из одного проекта в другой...
.xcdatamodeld
, которые находятся в целевом проекте.Закройте Xcode.
Использование Finder (или строки cmd);
.xcdatamodeld
..xcdatamodeld
.Переместите копию исходного файла .xcdatamodeld
в целевой проект.
Тогда...
.xcdatamodeld
в ваш проект..xcdatamodeld
(если необходимо) с помощью Навигатора проектов.Помогает ли это?
Если вы попытаетесь получить основные данные в своей структуре, сделайте это.
в YourFramework - добавить новые файлы/данные ядра/модель данных... - создать все объекты....
При создании нового проекта, который будет использовать YourFramework, убедитесь, что данные ядра находятся на
Это создаст всю плиту котла внутри AppDelegate.
в тестовом проекте - добавить Framework - добавить Framework как встроенную инфраструктуру - УДАЛИТЬ файл .xcdatamodeld - в AppDelegate:
изменить - (NSManagedObjectModel *)managedObjectModel
метод на:
NSBundle * testBundle = [NSBundle bundleWithIdentifier:@"YourFramework bundle id "];
NSURL *modelURL = [testBundle URLForResource:@"Model" withExtension:@"momd"];
где YourFramework bundle id
- идентификатор Bundle YourFramework (в общем/идентификатор пакета)
и Model
- это имя вашего файла .xcdatamodeld в YourFramework
Это работает.
Надеюсь, что это поможет.