Coredata — проблемы с Core Data


Содержание

Coredata — проблемы с Core Data

74 просмотра

1 ответ

142 Репутация автора

Я учу себя программировать и придумала этот проект для себя. У меня проблемы с моим кодом, я смог правильно его сохранить и загрузить первый штатный TVC. Тем не менее, у меня проблемы с состоянием и количеством животных на один государственный ТВЦ. Я хочу подвести итоги за штат. Так что я бы сложил популяцию собак и кошек и получил бы общее количество по штату, но это приносит Алабаму отдельно с двумя разными популяциями, может кто-нибудь помочь мне с этим, пожалуйста.

модель ниже показывает, как я этого хочу, я могу правильно выводить данные в State Population, но теперь второй.

Что касается моего кода для второго, так это то, что он получает данные из coredata, но я использую дескриптор сортировки, потому что я не знаю другого способа извлечения данных.

Ответы (1)

1 плюс

114574 Репутация автора

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

Вы можете использовать FRC, если обманываете . Установите для имени раздела FRC имя штата, тогда у вас будет один раздел в таблице на штат. В таблице делегат возвращает 1 для количества строк в каждом разделе. При настройке ячейки используйте KVC для @sum популяции всех животных в этом состоянии (строки для этого раздела в соответствии с пониманием FRC).

Это неэффективное решение для памяти и времени выполнения . Его можно улучшить, кэшируя вычисленные суммы, но тогда вы добавляете логику поверх плохого дизайна.

Правильный подход состоит в том, чтобы отказаться от FRC и использовать простой массив словарей. Это может быть сгенерировано путем изменения вашего запроса на выборку, чтобы он возвращал тип словаря, и настройки его для вычисления сумм для вас. Это сделано с выражением что-то вроде:

Coredata — проблемы с Core Data

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1

Сегодня хочу начать вольный перевод книги Михаеля Привата и Роберта Варнера «Pro Core Data for iOS», которую можете скачать по этой ссылке. Каждая глава будет содержать теоретическую и практическую часть.

  • Глава №1. Приступаем (Практическая часть)
  • Глава №2. Усваиваем Core Data
  • Глава №3. Хранение данных: SQLite и другие варианты
  • Глава №4. Создание модели данных
  • Глава №5. Работаем с объектами данных
  • Глава №6. Обработка результатирующих множеств
  • Глава №7. Настройка производительности и используемой памяти
  • Глава №8. Управление версиями и миграции
  • Глава №9. Управление таблицами с использованием NSFetchedResultsController
  • Глава №10. Использование Core Data в продвинутых приложениях

Что такое Core Data?

Используя компьютеры для выполнения своих задач, люди рассчитывают, что внесенные ими изменения будет сохранены. Сохранение изменений играет важную роль в офисных программных пакетах, текстовых редакторах, играх, браузерах и тд. Большинство программного обеспечения нуждается в возможности хранить введенные пользователем данные для последующего восстановления состояния работы, но конечно же есть и такое ПО, которое в этом не нуждается — калькуляторы, новостные ленты, будильники, виджеты о погоде.

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

Apple предоставляет гибкий фрэймворк для работы с хранимыми на устройстве данными — Core Data. Конечно же Core Data не панацея и есть другие варианты хранения данных, которые могут лучше подойти при решении определенных задач, но уж очень хорошо и красиво Core Data вписывается в Cocoa Touch. Большинство деталей по работе с хранилищем данных Core Data скрывает, позволяя вам сконцентрироваться на том, что действительно делает ваше приложение веселым, уникальным и удобным в использовании.

Не смотря на то, что Core Data может хранить данные в реляционной базе данных вроде SQLite, Core Data не является СУБД. По-правде Core Data в качестве хранилища может вообще не использовать реляционные базы данных. Core Data не является чем-то вроде Hibernate, хотя и предоставляет некоторые возможности ORM. Core Data скорее является оболочкой/фрэймворком для работы с данными, которая позволяет работать с сущностями и их связями (отношениями к другим объектами), атрибутами, в том виде, который напоминает работы с объектным графом в обычном объектно-ориентированном программировании.

Core Data был внедрён лишь начиная с Mac OS X 10.4 Tiger и iPhone SDK 3.0

История хранения данных в iOS

Как за выпущенные Pixar мультфильмы мы должны благодарить компанию NeXT, так и за Core Data мы должны сказать ей спасибо. Core Data родилась и эволюционировала из технологии, называемой Enterprise Objects Framework (EOF).

Дебют фрэймворка приходится на 2005 год с запуском Mac OS X 10.4 (Tiger), а вот в IPhone появляется лишь начиная с версии 3.0.

До того, как Core Data пришла на IPhone, разработчикам приходилось не сладко и для хранения данных могли быть использованы следующие варианты:

1) Списки свойств, которые содержали пары ключ-значение из различных типов данных.

2) Сериализация данных и хранение их в файлах (использовался протокол NSCoding)

3) Реляционная база данных SQLite

4) Хранение данных в облаке

Эти методы всё еще продолжают использоваться, хотя и ни один метод из четырёх не сравнится по удобству с использованием Core Data. Несмотря на рождение таких фрэймворком, как FMDatabase и ActiveRecord, для решения проблемы с хранением данных до появления Core Data, разработчики с удовольствием переключились на Core Data после его появления.

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

Чем чаще и чем больше вы будете программировать и использовать Core Data, тем чаще у вас будет возникать не вопрос «Стоит ли мне использовать Core Data?», а «Есть ли причина не использовать Core Data?».

Создание простого приложения с Core Data

В этой секции мы создадим простое приложение основанное на Core Data из одного из шаблонов XCode, основные части которого разберём. В конце этой части вы поймете, каким образом приложение взаимодействует с Core Data для хранения и получения данных.

Понимание основных компонентов Core Data

Перед тем, как погрузиться в код и разбор тестового приложения, необходимо иметь представление о компонентах Core Data. На рисунке ниже продемонстрированы основные элементы, которые мы будем использовать в тестовом приложении.

Как пользователь Core Data вы никогда не должны работать напрямую с хранилищем данных. Абстрагируйтесь от хранилища, от типа хранилища, думайте только о данных! Особенностью такого подхода является возможность безболезненно сменить тип хранилища (был XML файл, а стал SQLite) не меняя большое кол-ва написанного вами кода.

Объекты, которые находятся под управлением фрэймворка (Core Data) должны наследовать методы/свойства класса NSManagedObject.

Так же, как и людям, объектам нужна среда в которой они могут существовать, такая среда есть и, называется она managed object context (среда управляемых объектов) или просто context. Среда, в которой находится объект, следить не только за тем, в каком состоянии находится объект с которым вы работаете, но и за состояниями связанных объектов (объектов, которые зависимы от данного и от которых зависим он сам).

Экземпляр класса NSManagedObjectContext предоставляет ту самую среду для объектов, объект данного типа должен быть доступен в вашем приложении всегда. Обычно экземпляр класса NSManagedObjectContext является свойством делегата вашего приложения. Без среды, без экземпляра класса NSManagedObjectContext вам просто не удастся работать с Core Data.

Создание нового проекта

Запустим XCode и создадим новый проект из шаблона Master-Detail Application:

Заполним поля следующим образом:

И после завершения создания увидим примерно такую картину:

Запускаем наш проект

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

Жмём на кнопку «Run» и перед нами появится вот такое:

Нажмем несколько раз на кнопку с «+» и в списке появится несколько записей со временем.

Теперь завершим (остановим) работу приложения и, если приложение не использовало бы Core Data для хранения данных, то при очередном запуске мы увидели бы пустой список снова, однако после перезапуска мы видим всё ту же картину:

Разбираем составляющие приложения

Структура приложения относительно проста. В наличие имеется модель данных, которая описывает сущность хранимую в базе данных (хранилище); контроллер, который облегчает взаимодействия между экраном (таблицей) и хранилищем данных; делегат приложения, который помогает инициализировать и запустить приложение.

На изображении представленном ниже показаны классы используемые в приложении и как они соотносятся друг с другом:

Обратите внимание на то, что класс MasterViewController содержит свойство, которое ссылается на экземпляр класса NSManagedObjectContext для взаимодействия с Core Data. Пройдясь по коду можно увидеть, что MasterViewController получает managed object context из свойства делегата приложения.

— (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
<
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) <
self.title = NSLocalizedString(@»Master», @»Master»);
> self.managedObjectContext = [delegate managedObjectContext];
>

BasicApplication.xcdatamodel представляет собой директорию в файловой системе, которая содержит информацию о структуре модели данных. Модель данных является основой каждого приложения использующего Core Data.

Модель данных данного приложения описывает лишь одну сущность — Event. Сущность Event содержит лишь одно свойство (поле, атрибут) — timeStamp типа Date.

Сущность Event типа NSManagedObject, который считается основным для всех сущностей находящимся под управлением Core Data. Во второй главе мы рассмотрим тип NSManagedObject более подробно.

Следующим классом, который нас интересует, является MasterViewController. В его заголовочном файле описаны два свойства на которые мы обратим внимание:

@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

NSFetchedResultsController представляет собой контроллер, предоставляемый фрэймворком Core Data для управления запросами к хранилищу.

NSManagedObjectContext является известной нам уже средой существования объектов типа NSManagedObject.

Реализация класса MasterViewController, которую можно найти в файле MasterViewController.m, показывает, каким образом можно взаимодействовать с Core Data для получения и хранения данных. В реализации класса MasterVIewController имеется явный геттер fetchedResultsController, который производит предварительную настройку запроса на выборку данных из хранилища.

Первым шагом к осуществлению запроса на выборку данных является создание запроса:


NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@»Event» inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

Результаты запроса могут быть отсортированы при помощи NSSortDescriptor. NSSortDescriptor определяет поле для сортировки и тип сортировки (по возрастанию или убыванию).

В нашем примере сортируем по убыванию времена создания записей:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@»timeStamp» ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

После того, как запрос определен, мы можем приступить к созданию NSFetchedResultsController.

Используя в качестве делегата NSFetchedResultsController MasterVIewController мы можем следить за состоянием данных хранилища (удаление, добавление, перемещение и тд) и безболезненно интегрировать данное решение с UITableView. Мы можем конечно же получить те же результаты вызывая метод executeFetchRequest в managed object context, но в таком случае мы не получим и не сможем воспользоваться всеми преимуществами NSFetchedResultsController.

Создание и настройка переменной экземпляра класса NSFetchedResultsController:

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@»Master»];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

Вы наверно заметили, что используемый ранее метод initWithFetchRequest имеет параметр cacheName. При передаче в качестве аргумента nil Вы исключаете возможность кэширования результата запроса, но при указании наименования кэша, вы позволяете Core Data проверить наличие такого же ранее осуществленного запроса и вернуть результат из кэша. В противном случае, если запроса с таким именем кэша нет, то будет осуществлен запрос к хранилищу и возвращены необходимые данные, которые будет закэшированы впоследствии.

В завершение нам осталось только выполнить запрос для получения данных:

Ниже вы можете ознакомиться с полным геттером fetchedResultsController:

— (NSFetchedResultsController *)fetchedResultsController
<
if (_fetchedResultsController != nil)
return _fetchedResultsController;

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@»Event» inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@»timeStamp» ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@»Master»];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

NSFetchedResultsController представляет собой нечто вроде коллекции объектов типа NSManagedObject, для этого у него даже имеется свойства fetchedObjects типа NSArray для получения доступа к результатам запроса.

Класс MasterVIewController, который так же расширяет возможности UITableViewController, демонстрирует нам насколько удобно использовать NSFetchedResultsController для управления содержимым таблиц.

Вставка нового объекта

Быстро окинув взглядом метод insertNewObject: станет понятно, каким образом создаются и добавляются новые события в хранилище. NSManagedObject определяются описанием сущности из модели данных и могут существовать только в определенном контексте (среде). Первым шагом для создания нового объекта является получение контекста в котором этот объект будет создан:

NSManagedObjectContext *managedObjectContext = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];

NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntity:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:@»timeStamp»];

Последним шагом, который необходимо осуществить, является сохранение контекста в котором был создан новый объект. Учтите, что при сохранении контекста все несохраненные ранее изменения будут сохранены.

Полный метод добавления нового объекта представлен ниже:

— (void)insertNewObject <
NSManagedObjectContext *managedObjectContext = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

[newManagedObject setValue:[NSDate date] forKey:@»timeStamp»];

Инициализация контекста (среды)

Очевидно, что всё, что мы раньше делали не может быть достигнуто без создания объекта контекста, без той самой среды в которой существует и живет объект. Как раз за создание этой самой среды отвечает делегат приложения. Три свойства, которые должны быть обязательно в любом приложении использующем Core Data приложении:

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

Обратите внимание на то, что все три свойства readonly, делается это для того, чтобы извне их нельзя было установить. Изучая BasicApplicationAppDelegate.m видно, что все три свойства имеют явные геттеры.

Managed Object Model:

— (NSManagedObjectModel *)managedObjectModel <
if(_managedObjectModel != nil) <
return _managedObjectModel;
>

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@»BasicApplication» withExtension:@»momd»];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modeURL];

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

— (NSPersistentStoreCoordinator *)persistentStoreCoordinator <
if(_persistentStoreCoordinator != nil) <
return _persistentStoreCoordinator;
>

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@»BasicApplication.sqlite»];

NSError* error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) <
NSLog(@»Unresolved error %@, %@», error, [error userInfo]);
abort();
>

Создаём контекст (среду):

— (NSManagedObjectContext *)managedObjectContext <
if(_managedObjectContext != nil) <
return _managedObjectContext;
>

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if(coordinator != nil) <
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
>

Контекст используется во всём приложении в качестве интерфейса для взаимодействия с Core Data и постоянным хранилищем.

Последовательность инициализации Core Data:

Механизм запускается при вызове метода application:didFinishLaunchingWithOptions:

— (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions <
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

MasterViewController *controller = [[MasterViewController alloc] initWithNibName:@»MasterViewController» bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
self.window.rootViewController = self.navigationController;

[self.window makeKeyAndVisible];
return YES;
>

Вызывая геттер свойства managedObjectContext делегата приложения на выполнение запускается цепочка действий:

— (NSManagedObjectContext *)managedObjectContext вызывает

— (NSPersistentStoreCoordinator *)persistentStoreCoordinator, который в свою очередь производит вызов

Таким образом вызов геттер-метода managedObjectContext инициализирует весь стэк объектов Core Data и приводит Core Data в готовность.

Добавление Core Data в уже существующий проект

Осуществляется в три шага:

  1. Добавление фрэймворка Core Data
  2. Создание модели данных
  3. Инициализация контекста (среды)

Добавление фрэймворка Core Data

В мире Objective-C библиотеки называют фрэймворками.

Стандартные фрэймворки, которые уже подключены в «чистых» проектах и которые вы чаще всего увидите:

Где производится добавление новых фрэймворков:

Выбираем фрэймворк для подключения:

Создание модели данных

Ни одно приложение Core Data не может считаться завершенным без модели данных. Модель данных описывает все сущности, которые будут находиться в ведении Core Data.

Для создания новой модели данных: File -> New -> New File

Назовем нашу модель MyModel.xcdatamodeld:

После создания модели перед вами откроется окно редактирования (создания) сущностей.

Создать новую сущность можно кликнув на кнопку «+» в левой нижней части XCode, а добавить новый атрибут сущности можно нажав на кнопку «+» уже в разделе «Attributes» и затем выбрать его тип.

Инициализация контекста (среды)

Последний шаг состоит в инициализации контекста, хранилища и объектной модели. Чаще всего вы можете воспользоваться кодом, который автоматически генерируется XCode в «пустых» проектах использующих Core Data.

@interface DemoAppDelegate : UIResponder <
>


@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navigationController;

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

— (void)saveContext;
— (NSURL *)applicationsDocumentsDirectory;

Переключимся в *.m файл DemoAppAppDelegate и напишем следующие строки:

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

Далее следует код, который производит инициализацию модели данных, хранилища и контекста.

— (NSManagedObjectModel *)managedObjectModel <
if (_managedObjectModel != nil) <
return _managedObjectModel;
>

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@»MyModel» withExtension:@»momd»];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modeURL];

— (NSPersistentStoreCoordinator *)persistentStoreCoordinator <
if(_persistentStoreCoordinator != nil) <
return _persistentStoreCoordinator;
>

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@»DemoApp.sqlite»];

NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error&error]) <
NSLog(@»Unresolved error %@, %@», error, [error userInfo]);
abort();
>

— (NSManagedObjectContext *)managedObjectContext <
if(_managedObjectContext != nil) <
return _managedObjectContext;
>

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if(coordinator != nil) <
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
>

Методы, который ранее мы еще нигде не реализовывали:

— (NSURL *)applicationDocumentsDirectory <
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
>

— (void)saveContext <
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

Теперь, когда мы подключили Core Data, наше приложение может использовать его для хранения данных.

Давайте реализуем простой пример, который бы позволил нам убедиться в том, что всё работает так, как надо и данные действительно сохраняются.

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

Внесём маленькие изменения в метод application:didFinishLaunchingWithOptions: делегата приложения в виде получения кол-ва раз, которое приложения запускалось ранее и добавление нового события запуска.

Код для получения предыдущих запусков приложения:

NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@»MyData» inManagedObjectContext:context];
[request setEntity:entity];
NSArray *results = [context executeFetchRequest:request error:nil];

После чего мы можем пройтись по всему массиву следующим образом:

for(NSManagedObject *object in results) <
NSLog(@»Found %@», [object valueForKey:@»myAttribute»];
>

Добавим новую запись и сохраним:

NSString *launchTitle = [NSString stringWithFormat:@»launch %d», [results count]];
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[object setValue:launchTitle forKey:@»myAttribute»];
[self saveContext];
NSLog(@»Added : %@», launchTitle);

После первого запуска приложение выведет в консоль следующую строку:

2011–02-25 05:13:23.783 DemoApp[2299:207] Added: launch 0

После второго запуска:

2011–02-25 05:15:48.883 DemoApp[2372:207] Found launch 0
2011–02-25 05:15:48.889 DemoApp[2372:207] Added: launch 1

Полный метод выглядит следующим образом:

— (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions <
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entytyForName:@»MyData» inManagedObjectContext:context];
[request setEntity:entity];
NSArray *results = [context executeFetchRequest:request error:nil];

for(NSManagedObject *object in results) <
NSLog(@»Found %@», [object valueForKey:@»myAttribute»]);
>

NSString *launchTitle = [NSString stringWithFormat:@»launch %d», [results count]];
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[object setValue:launchTitle forKey:@»myAttribute»];
[self saveContext];
NSLog(@»Added : %@», launchTitle);

[self.window makeKeyAndVisible];
return YES;
>

Прошу об ошибках не писать в комментариях, лучше сразу в личные сообщения.

Продолжать ли переводы? Есть ли интерес к данной теме?

Core Data / 1.1. Основы Core Data

Футбол состоит из побед и поражений, главное — не останавливаться из-за трудностей.

В этом уроке

  • Стэк Core Data
  • Модель данных
  • Свойства моделей
  • Добавления новых объектов в контекст

Зачем нужна Core Data?

Раньше мы видели множество способов для хранения данных — текстовые файлы, plist, xml, json. Но все они имеют множество недостатков для хранения на устройстве пользователя, начиная от рутины по обработке и заканчивая низкой производительностью для больших объемов данных.

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

Есть несколько основных вариантов баз данных — SQL или реляционные (хотя понятия несинонимичны, они часто существуют бок-о-бок), NoSQL и базы данных на основе графов. Каждая из них имеет свои особенности и цели применения — нельзя сказать, что какая-то из них лучше другой (если говорить о конкретных продуктах, то старайтесь избегать поделки Microsoft под названием MS SQL Server).

В основе хранения данных на устройстве пользователя лежит SQLite-база данных. Она специально предназначена для интеграции в приложения и единичное использование — при оперировании ею с помощью Core Data доступ к базе данных будет иметь только Ваше приложение, размещаться она будет в папке Library песочницы, куда у пользователя нет доступа.

Core Data и Вы

Мы создадим приложение для списка дел — мы сильно упростим его по сравнению с изначальным вариантом, который мы уже делали и сохраняли данные на диск кустарными методами.

  • Создайте новое Single View приложение, при этом галочку у Core Data мы всё равно ставить не будем — мы должны понять как всё это работает самостоятельно, а готовый вариант лишь затруднит написание кода с нуля.
Цукерберг рекомендует:  3D Grid Effect Demo 1

До iOS 10 пользователям приходилось работать напрямую со стэком Core Data — такая возможность имеется и сейчас, если Вам нужен больший контроль над всем этим, однако все элементы теперь объединены в очень удобную штучку — Persistent Container .

В AppDelegate мы добавим два удобных метода для извлечения контейнера данных:

Казалось бы — очень простой метод. И что же может пойти не так? Ответ прост — почти всё:

  • Родительская директория не существует, не может быть создана или запрещает запись (наиболее вероятная проблема для macOS)
  • Хранилище недоступно из-за разрешений пользователя, или так как устройство заблокировано (устройства Apple умеют при блокировке, оставаясь включенными блокировать доступ к данным, чтобы люди не могли их извлечь методами пещерных людей (молоток и отвертка)
  • Отсутствует свободное место для контейнера
  • Хранилище не может быть мигрировано до последней версии модели (про миграции мы расскажем чуть позже)

В полифункциональных приложениях Вы вероятно захотите вынести функционал данных в отдельный сервис-класс.

Следующий метод позволит сохранить контекст в контейнер:

Этот метод может сломаться по тем же причинам.

Модель данных

  1. Нажмите CMD + N для создания нового файла
  2. Найдите секцию Core Data

  3. Выберите Data Model В качестве названия укажите SWCoreData1 , что позволит приложению загружать модель.

Теперь перейдите в этот файл в инспекторе файлов:

В первое знакомство это окно может вызвать чувство страха.

Core Data умеет работать не только с базами данных, но и создавать хранилища в памяти, писать в XML (только на macOS), а также в бинарный формат. До тех пор, пока не поймёте, что Вы не решите проблему без указанных вещей — не используйте их.

Нажмите по плюсу у Add Entity. Это создаст новую запись в системе — запись можно считать эквивалентной классу, только с тем исключением, что она лежит в системе контроля данных, а управлять ей могут совсем другие классы (скорее всего Вам не придётся так извращаться).

Дайте ей название List — это будет список дел.

В центральной панели у нас есть 3 большие секции:

  • Attributes — Атрибуты модели — схожи со свойствами объектов
  • Relationships — Отношения между моделями
  • Fetched Properties — специальные слабые отношения, которые позволяют подтягивать другие отношения в виде запроса — иногда они могут сильно Вас запутать, потому при необходимости не используйте их часто.

Давайте добавим атрибут name типа String в модель.
Есть множество типов данных для модели, которые прозрачно превращаются в те, что заложены в SQLite .

Заметьте, что здесь нет простого типа Int — в Objective-C он является примитивом, а числовые типы выражаются через знакомый нам NSNumber.

Справа нам доступен новый инспектор для моделей:

  • Properties — Вы можете сделать свойство опциональным (по-умолчанию все свойства такие) или же переходным transient — такое свойство, хоть и управляется Core Data, не хранится в базе данных. Эти два пункта нельзя сочетать вместе. Уберите опциональность у имени списка дел.
  • Следующий блок посвящён валидации поля — он меняет в зависимости от атрибута — для строки можно задать минимальную, максимальную длины, значение по-умолчанию и регулярное выражение, которому должна соответствовать строка. Нам важно, чтобы нельзя было давать слишком короткие названия — менее 4 символов.
  • Блок UserInfo позволяет добавить к модели атрибуты, подставляемые во время выполнения.

Теперь Выберите сам класс целиком:

  • Abstract Entity — Можно сделать запись абстрактной, тогда она будет использоваться для создания других записей, но её объекты не будут созданы, ровно как и записаны на диск
  • Parent Entity Классы в Core Data можно строить друг на основе друга — но наследование таких классов отличается от обычного — они будут жить в одной таблице в базе данных, при этом иметь общими полями все, что есть у всех моделей, просто они будут принимать нулевые значения. Потому наследуйте записи только при крайней необходимости, иначе столкнётесь с проблемой разреженных баз данных — когда таблицы будут иметь большое число NULL-значения.

NULL — это аналог nil в мире баз данных, показывающий что какого-то значения нет.

Мы хотим показать, что происходит у неё под юбкой, а потому выберем ручное создание класса. Теперь Выберите класс и нажмите в верхнем меню Editor -> Create NSManagedObject Subclass.

Давайте посмотрим содержание двух файлов:

NSManagedObject — это специальный наследник NSObject , который позволяет объекту жить не просто в рантайме objc, но и в среде Core Data, которая управляет его поведением — такому объекту не нужно реализовывать многие свои методы и свойства — они будут добавлены на лету.

На данный момент кодогенерация даёт нам следующий второй файл:

И здесь для нас много нового — первый метод класса позволяет конструировать запросы к этому классу в базе данных, при этом он не экспортируется в objc — в ней уже есть метод с таким же названием, который не специализируется конкретным типом и возвращает голый объект, а в этом варианте C недоступна перегрузка функций.

Второй интересный момент — атрибут @NSManaged , который говорит системе, что это свойство управляется Core Data и будет добавлено на лету, а потому за него можно не волноваться.

Заметьте, что имя сгенерировалось опционалом (в большинстве случаев) — нам просто нужно убрать знак вопроса у строки. Это известное поведение кодогенерации и остаётся лишь надеяться, что его исправят.

И хотя Core Data использует в большинстве случаев под собой базы данных — она не является базой данных или системой управления баз данных. База данных SQLite лишь выступает хранилищем для объектов Core Data. Core Data — это граф объектов в памяти с их отношениями и свойствами. То, как он будет существовать в том или ином месте — решать Core Data. Думайте о ней как об ещё одном способе сохранения объектов. Для обычных SQL баз данных хорошим способом оптимизации выступает нормализация таблиц, но здесь она может вызвать обратный эффект.

Скелет приложения

Теперь необходимо создать скелет приложения, чтобы мы могли продемонстрировать Вам весь функционал Core Data.

  1. Встройте наш единственный контроллер в контроллер навигации
  2. Задайте ему заголовок To Do Lists
  3. Поместите на него табличное представление:
    • Задайте ему нулевые отступы от границ
    • Делегат и источник данных — контроллер
    • Аутлет tableView
  4. В таблице сделайте одну динамическую ячейку:
    • Стиль — с подзаголовком
    • Индикатор detail
    • Идентификатор ListCell

В его файле создадим несколько свойств для удобства:

В реальном приложении их лучше вынести в стек Core Data

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

Реализуйте протоколы источника и делегата табличного представления (делегат пока что будет пуст, а ячейка в качестве заголовка должна содержать название списка дел):

Теперь пропишем одну специальную функцию, которая будет создавать запросы по извлечению данных:

Извлечение объектов может провалится по множеству причин, потому его надо соответственно перехватить.

Теперь во viewDidLoad мы добавим извлечение контейнера, контекста и данных:

Добавление нового объекта в контекст

Все хорошо, но данных-то у нас нет и взяться им неоткуда. Создадим ещё одну форму для добавления списка дел.

Сперва создайте класс AddListTableViewController , унаследовав его от сами знаете чего. После его генерации удалите из него всю внутреннюю часть.

  1. На полотно перетащите Table View Controller
  2. Задайте ранее созданный класс
  3. На основном контролере создайте кнопку в правой части панели навигации со значком +
  4. От кнопки проведите show-сегвей к табличному контроллеру
  5. Задайте ему идентификатор ToAddList
  6. На том контроллере создайте кнопку Save с методом saveButtonPressed
  7. А заголовок Add List
  8. Переключите таблицу в статический режим
  9. Оставьте пока что лишь одну ячейку:
    1. Задайте ей высоту в 50 точек
    2. В неё поместите текстовое поле
    3. Его отступы должны быть нулевыми с учётом марджинов родительского представления
    4. Текст-заместитель — Name
    5. Аутлет — nameField

Для сохранения данных мы воспользуемся старым добрым методом с протоколом.

Создадим протокол для делегата в том же файле:

Теперь создайте слабое свойство-делегат:

А теперь закончим тело метода по сохранению объекта:

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

Первый пункт Вы можете сделать самостоятельно:

Второй же пункт несколько интереснее:

Каждый управляемый объект получает специальный конструктор для добавления в контекст, после чего нам нужно задать его свойства и сохранить контекст. Затем мы просто заново извлекаем данные.

Попробуйте создать свой список дел. Если же Вы зададите имя, меньшее 4 символов, то будет вызвана ошибка валидации примерно такого вида:

Лучшим поведением будет выдавать пользователю сообщения о проблемах валидации, а не ломать всё приложение при попытке сохранения данных.

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

Ограничения Core Data

Несмотря на всю свою красоту и мощь — Core Data очень слабо применима вне конечных приложений — её варианта нет для Linux-версии Swift, так как она построена поверх Objective-C и его элементов, а даже если бы она там и была — применять её для серверной части было бы неэффективно — SQLite хорошо подходит для лёгких приложений и встраиваемых систем, но не для поддержки больших сервисов.

Проблема с проверкой данных в CoreData

Так что я пытаюсь сохранить данные с минимальным значением 0 и максимальным значением 200 Если я печатаю в количестве между в соответствующем диапазоне он работает нормально, но если я пытаюсь ввести другой номер (-1 или 203, например) она застревает по этому значению. Оповещения контроллера представлен, но когда я пытаюсь ввести в правовом значении он показывает в консоли предыдущего значение (-1 или 203) и последние изменения стоимости, только если я тип в другом плохом номере (например, 509 и оповещение контроллер представлен также ). Я получаю ошибки 1610 и 1620, но я не понимаю, как это исправить. Мне нужно, чтобы убедиться, что если пользователь в неправильном значении, а затем хороший один все работает отлично, и она сохраняет данные.

Вот мой код для сохранения


В вашей saveNote функции вы направляете новый BreathingNote с let note = BreathingNote(context: context) . Затем установите значения этого объекта и попытаться сохранить его. Если не удается сохранить вам предложит пользователю исправить свои данные и в конечном итоге звонить saveNote снова, где вы создаете новый BreathingNote объект с обновленными данными.

Оригинал BreathingNote по — прежнему существует в контексте управляемого объекта, однако, когда вы звоните save , Core Data пытается сохранить оригинальную ноту и новый; Поскольку исходная нота все еще имеет плохие данные, спасброски снова терпит неудачу. Вы можете удалить записку с плохими данными по телефону

когда вы ловите неудачные сохранить; это будет удалить объект с недостоверными данными из контекста

Core Data с нуля: стек Core Data

Введение

Фреймворк Core Data существует уже много лет. Он используется в тысячах приложений и миллионами людей, как на iOS, так и на OS X. Core Data поддерживаются Apple и очень хорошо документированы. Это состоявшийся фреймворк, который доказывает свою ценность снова и снова.

Core Data использует преимущества языка Objective-C и его среды и плавно интегрируется с базой Core Foundation. Результат — простая в использовании инфраструктура для управления графом объектов, элегантный в использовании и невероятно эффективный с точки зрения использования памяти.

1. Требования

Несмотря на то, что Core Data не сложная сама по себе, если вы новичок в разработке на iOS или OS X, я рекомендую вам сначала ознакомиться с нашей серией уроков о разработке на iOS. Она научит вас основам разработки на iOS, и после завершения серии у вас будет достаточно знаний для изучения более сложных тем, таких как Core Data.

Как я уже сказал, Core Data не такая сложная для понимания, как думают многие разработчики. Тем не менее, я уверен, что хорошая база имеет решающее значение для ускорения работы с Core Data. У вас должно быть понимание API Core Data, чтобы избежать неправильного применения и убедиться, что вы не столкнётесь с проблемами при использовании фреймворка.

Каждый компонент Core Data имеет определенную цель и функцию. Если вы попытаетесь использовать Core Data таким образом, каким он не был задуман, вы неизбежно столкнетесь с трудностями использования фреймворка.

То, что я расскажу в этой серии о Core Data, применимо к iOS 6+ и OS X 10.8+, но основное внимание будет уделено iOS. В этой серии я буду работать с Xcode 5 и iOS 7 SDK.

2. Изучаем Кривые

Структура Core Data может показаться сложной на первый взгляд, но API становится интуитивно понятным и лаконичный, как только вы поймете, как различные части взаимодействуют друг с другом. И это именно та часть, где большинство разработчиков сталкиваются с проблемами. Они пытаются использовать Core Data, прежде чем они увидят весь пазл, и не знают, как части головоломки соотносятся друг с другом.

В этой статье я помогу вам ознакомиться с так называемым ядром Core Data. Как только вы поймете ключевые моменты в стеке Core Data, структура будет казаться менее сложной, и вы даже начнете наслаждаться и оцените хорошо продуманный API фреймворка.

В отличие от таких систем, как UIKit, которые вы можете использовать без понимания структуры в целом, Core Data требует правильного понимания своих компонентов. Важно уделить время, чтобы ознакомиться с фреймворком, что мы и сделаем в этом уроке.

3. Что такое Core Data?

Разработчики, новички в Core Data, часто ожидают, что она будет работать как база данных. Если и есть то, что я надеюсь вы запомните из этой серии, это то, что Core Data не является базой данных, и следовательно вы не должны ожидать, что она будет действовать как она.

Что такое Core Data, если это не база данных? это модельный уровень вашего приложения в самом широком смысле. Это модель в шаблоне Model-View-Controller который пронизывает IOS SDK.

Core Data — это не база данных для вашего приложения, а также API для хранения данных в базе данных. Core Data — это структура, управляющая графом объектов. Это все. Core Data может сохранять этот граф объектов, записывая его на диск, но это не основная цель структуры.

4. Стек Core Data

Как я уже упоминал ранее, ядро Core Data является основой Core Data. Это набор объектов, которые заставляют Core Data работать. Ключевыми объектами стека являются модель управляемых объектов, постоянный координатор хранилища и один или несколько контекстов управляемых объектов. Давайте начнем с быстрого анализа каждого компонента.

NSManagedObjectModel

Модель управляемых объектов — это модель данных приложения. Несмотря на то, что Core Data не является базой данных, вы можете сравнить модель управляемых объектов со схемой базы данных, то есть она содержит информацию о моделях или объектах графа, какие атрибуты они имеют и как они относятся к друг друга.

Объект NSManagedObjectModel знает о модели данных, загружая один или несколько файлов модели данных во время ее инициализации. Мы рассмотрим, как это работает через несколько мгновений.

NSPersistentStoreCoordinator

Как и указывает его имя, объект NSPersistentStoreCoordinator сохраняет данные на диске и гарантирует совместимость хранилищ и моделей данных. Он является посредником между постоянным хранилищем (хранилищами) и контекстом (-ами) управляемого объекта, а также занимается загрузкой и кэшированием данных. Так и есть. В Core Data встроено кэширование.

Постоянный координатор хранилища является проводником оркестра Core Data. Несмотря на свою важную роль в стеке Core Data, мы редко взаимодействуем с ним напрямую.

NSManagedObjectContext

Объект NSManagedObjectContext управляет набором объектов модели, экземплярами класса NSManagedObject . Возможно иметь несколько контекстов управляемых объектов. Каждый контекст управляемого объекта поддерживается постоянным координатором хранилища.

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

Хотя модель управляемых объектов и постоянный координатор хранилища могут быть разделены между потоками, контексты управляемых объектов никогда не должны быть доступны из потока, отличного от того, в котором они были созданы. Мы обсудим многопоточность более подробно позже в этой серии.

5. Изучение стека Core Data

Шаг 1: Шаблон Xcode

Давайте рассмотрим стек Core Data более подробно, взглянув на шаблон Xcode Apple для Core Data. Создайте новый проект в Xcode 5, выбрав New > Project. в меню File. Выберите шаблон Пустое приложение из списка шаблонов приложений iOS слева.

Назовите проект Core Data, установите Devices на значение iPhone и установите флажок Использовать основные данные. Укажите Xcode, где вы хотите сохранить файлы проекта и нажмите Создать.

Шаг 2: Обзор

По умолчанию Apple помещает код, связанный с Core Data в класс делегирования приложения, класс TSPAppDelegate в нашем примере. Начнем с изучения интерфейса TSPAppDelegate .

Как вы можете видеть, делегат приложения имеет свойство для каждого компонента стека основных данных, а также два удобных метода: saveContext и applicationDocumentsDirectory .

Обратите внимание, что свойства Core Data отмечены как readonly , что означает, что экземпляры не могут быть изменены объектами, отличными от самого приложения.

Реализация TSPAppDelegate гораздо интереснее и покажет нам, как работающая модель объекта, постоянный координатор хранилища и контекст управляемых объектов работают вместе. Начнем с начала.

Поскольку свойства в интерфейсе класса TSPAppDelegate объявляются как readonly, не создаются методы setter. Первая директива @synthesize сообщает компилятору связать переменную экземпляра _managedObjectContext с свойством managedObjectContext , которое мы объявили в интерфейсе класса. Это общий шаблон для поэтапной загрузки объектов.

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

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

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

На практике это означает, что реализация класса TSPAppDelegate похожа на то, что вы ожидаете в классе делегирования приложения, за исключением методов saveContext и applicationDocumentsDirectory , а также методов getter для управляемого ObjectContext , managedObjectModel и persistentStoreCoordinator . Именно в этих методах происходит волшебство. Это одна из жемчужин Core Data, настройка очень проста и взаимодействие с Core Data так же проста.

Шаг 3: Контекст управляемого объекта

Класс, который вы будете использовать чаще всего, помимо NSManagedObject , при взаимодействии с основными данными — это NSManagedObjectContext . Начнем с изучения его геттера.

Первые три строки его реализации типичны для геттера, который поэтапно загружает переменную экземпляра. Если объект NSManagedObjectContext не равен null , он возвращает объект. Интересный момент — это фактическое создание объекта NSManagedObjectContext .

Сначала мы получаем ссылку на координатор хранилища сохранения, вызывая его метод getter. Постоянный координатор хранилища также загружается поэтапно, как мы увидим в следующий момент. Если постоянный координатор хранилища не равен null , мы создаем экземпляр NSManagedObjectContext и устанавливаемего свойство persistentStoreCoordinator и передаем его постоянному координатору хранилища. Это было не слишком сложно. Не так ли?

Таким образом, контекст управляемого объекта управляет набором объектов модели, экземплярами класса NSManagedObject и сохраняет ссылку на постоянный координатор хранилища. Помните об этом, читая остальную часть этой статьи.

Шаг 4: Постоянный координатор хранилища

Как мы уже видели, метод persistentStoreCoordinator вызывается методом managedObjectContext . Взгляните на реализацию persistentStoreCoordinator , но не позволяйте этому напугать вас. На самом деле это не так сложно.

Вы наверняка захотите сохранить граф объектов Core Data на диске, а шаблон Xcode Apple использует базу данных SQLite для достижения этой цели.

Когда мы создаем постоянный координатор хранилища в persistentStoreCoordinator , мы указываем местоположение хранилища на диске. Начнем с создания объекта NSURL , который указывает на это место в изолированной программной среде приложения. Мы вызываем applicationDocumentsDirectory , вспомогательный метод, который возвращает местоположение, объект NSURL , в каталоге Documents в изолированной программной среде приложения. Мы добавляем Core_Data.sqlite к местоположению и сохраняем его в storeURL для последующего использования.

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

Как я уже говорил, расширение .sqlite подсказывает, что хранилище на диске представляет собой базу данных SQLite. Несмотря на то, что Core Data поддерживает несколько типов хранилищ, SQLite на сегодняшний день является наиболее используемым типом хранилища из-за его скорости и надежности.

На следующем шаге мы создаем экземпляр постоянного координатора хранилища, вызывая initWithManagedObjectModel: и передаем экземпляр NSManagedObjectModel . Мы получаем ссылку на модель управляемых объектов, вызывая метод managedObjectModel , который мы рассмотрим далее.

Теперь у нас есть экземпляр класса NSPersistentStoreCoordinator , но пока нет связанного с ним хранилища. Мы добавляем хранилище к постоянному координатору, вызывая довольно впечатляющий метод: addPersistentStoreWithType: configuration:URL:options:error: .

Первый аргумент указывает тип хранилища NSSQLiteStoreType в этом примере. Core Data также поддерживает двоичные хранилища ( NSBinaryStoreType ) и хранилище в памяти ( NSInMemoryStoreType ).

Второй аргумент сообщает Core Data, какую конфигурацию использовать для постоянного хранилища. Мы передаем null , который сообщает Core Data использовать конфигурацию по умолчанию. Третий аргумент — это местоположение хранилища, которое хранится в storeURL .

Четвертый аргумент — это NSDictionary — опции, которые позволяют нам изменять поведение постоянного хранилища. Мы рассмотрим этот аспект позже в этой серии и перейдем сейчас к null . Последний аргумент — ссылка на указатель NSError .

Если ошибки не появляются, этот метод возвращает объект NSPersistentStore . Мы не сохраняем ссылки на постоянное хранилище, потому что нам не нужно взаимодействовать с ним, как только он добавляется в постоянный координатор.

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

На данный момент abort вызывается, когда addPersistentStoreWithType:configuration:URL:options:error: возвращает null . Как поясняют комментарии в инструкции if , вы никогда не должны вызывать abort в рабочей среде, потому что это приводит к сбою приложения. Мы исправим это позже в нашей серии.

Шаг 5: Управляемая модель объекта

Третий и последний фрагмент головоломки — это модель управляемых объектов. Давайте посмотрим на getter свойства managedObjectModel .


Реализация его очень проста. Мы сохраняем местоположение модели приложения в modelURL и передаем modelURL в initWithContentsOfURL: для создания экземпляра класса NSManagedObjectModel .

На данный момент вы, вероятно, задаетесь вопросом, на что указывает модель ModelURL , и что такое файл с расширением .momd . Чтобы ответить на эти вопросы, нам нужно выяснить, что еще создал Xcode для нас во время настройки проекта.

В Навигаторе проектов слева вы должны увидеть файл с именем Core_Data.xcdatamodeld. Это модель данных приложения, скомпилированный в файл .momd . Это файл .momd , который использует модель управляемых объектов для создания модели данных приложения.

Возможна ситуация когда у вас есть сразу несколько файлов модели данных. Класс NSManagedObjectModel отлично способен объединить несколько моделей данных в один, что является одной из наиболее мощных и продвинутых функций Core Data.

Структура Core Data также поддерживает моделирование версий данных, а также миграции. Это гарантирует, что данные, хранящиеся в постоянных хранилищах, не будут повреждены. В этой серии мы расскажем о версиях и миграции.

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

6. Соединяем все вместе

Прежде чем мы закончим эту статью, я хотел бы показать вам диаграмму, иллюстрирующую три компонента стека Core Data.

Вышеприведенная диаграмма — это визуальное представление того, что мы изучили в шаблоне Xcode мгновение назад. Объект NSPersistentStoreCoordinator является мозгом стека основных данных приложения. Он ведет переговоры с одним или несколькими постоянными хранилищами и гарантирует сохранение, загрузку и кэширование данных.

Постоянный координатор хранилища знает о модели данных, схеме графического объекта, если хотите, через объект NSManagedObjectModel . Модель управляемых объектов создает модель данных приложения из одного или нескольких файлов .momd , двоичных представлений модели данных.

И последнее, но не менее важное: приложение обращается к графу объектов через один или несколько экземпляров класса NSManagedObjectContext . Контекст управляемого объекта знает о модели данных через постоянный координатор хранилища, но он не знает или не поддерживает ссылку на модель управляемых объектов. Нет необходимости в этом соединении.

Цукерберг рекомендует:  Игры - Требуется начинающий Frontend-разработчик (React + верстка)

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

Заключение

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

В следующем выпуске этой серии посвященной Core Data мы погрузимся в изучение модели данных. Мы рассмотрим редактор модели данных в Xcode 5, и мы создаем несколько сущностей, атрибутов и отношений.

Как устранить сообщения об ошибках Core.data.dll отсутствует / не найден

Совместима с Windows 2000, XP, Vista, 7, 8 и 10

Обзор Core.data.dll

Что такое Core.data.dll?

Core.data.dll представляет собой разновидность файла DLL, связанного с Xactimate, который разработан Xactware для ОС Windows. Последняя известная версия Core.data.dll: 27.3.1088.23556, разработана для Windows Vista. Данный файл DLL имеет рейтинг популярности 1 звезд и рейтинг безопасности «UNKNOWN».

Что из себя представляют файлы DLL?

Файлы DLL («динамически подключаемая библиотека»), такие как core.data.dll – это небольшие программы, схожие с файлами EXE («исполняемыми»), которые позволяют множеству программ использовать одни и те же функции (например, печать).

Например, когда вы запускаете Windows Vista и редактируете документ в Microsoft Word. Необходимо загружать файл DLL, контролирующий печать, только если его функции востребованы — например, когда вы решили распечатать свой документ. Когда вы выбираете «Печать», Microsoft Word вызывает файл принтера DLL, и он загружается в память (RAM). Если вы хотите распечатать документ в другой программе, например в Adobe Acrobat, будет использоваться тот же самый файл принтера DLL.

Почему у меня наблюдаются ошибки в файлах типа DLL?

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

Проще говоря, если Windows не может корректно загрузить файл core.data.dll, вы получите сообщение об ошибке. Для получения дополнительной информации см. «Причины ошибок core.data.dll» ниже.

В каких случаях появляются ошибки в файлах типа DLL?

Ошибки DLL, например, связанные с core.data.dll, чаще всего появляются во время запуска компьютера, запуска программы или при попытке использования специфических функций в вашей программе (например, печать).

Распространенные сообщения об ошибках в Core.data.dll

Наиболее распространенные ошибки core.data.dll, которые могут возникнуть на компьютере под управлением Windows, перечислены ниже:

  • «Core.data.dll не найден.»
  • «Файл core.data.dll отсутствует.»
  • «Core.data.dll нарушение прав доступа.»
  • «Файл core.data.dll не удалось зарегистрировать.»
  • «Файл %PROGRAMFILES%\Xactware\Xactimate27\CORE\core.data.dll не найден.»
  • «Не удалось запустить Xactimate. Отсутствует необходимый компонент: core.data.dll. Пожалуйста, установите Xactimate заново.»
  • «Не удалось запустить данное приложение, так как не найден файл core.data.dll. Повторная установка приложения может решить эту проблему.»

Такие сообщения об ошибках DLL могут появляться в процессе установки программы, когда запущена программа, связанная с core.data.dll (например, Xactimate), при запуске или завершении работы Windows, или даже при установке операционной системы Windows. Отслеживание момента появления ошибки core.data.dll является важной информацией при устранении проблемы.

Причины ошибок в файле Core.data.dll

Большинство ошибок core.data.dll связано с отсутствием или повреждениями файлов core.data.dll. Тот факт, что core.data.dll – внешний файл, открывает возможность для всяческих нежелательных последствий.

Непредвиденные завершения работы вашего компьютера или заражение вирусом может повредить core.data.dll, что приведет к ошибкам DLL. Когда файл core.data.dll повреждается, он не может быть нормально загружен и выведет сообщение об ошибке.

В других случаях ошибки файла core.data.dll могут быть связаны с проблемами в реестре Windows. Нерабочие ссылки DLL файлов могут помешать зарегистрировать файл DLL должным образом и вызвать ошибку core.data.dll. Эти нерабочие ключи реестра могут появиться в результате отсутствия файла DLL, перемещения файла DLL или ввиду наличия остаточной ссылки DLL файла в реестре Windows после неудачной установки или удаления программы.

Более конкретно, данные ошибки core.data.dll могут быть вызваны следующими причинами:

  • Ошибочные или поврежденные записи реестра для core.data.dll
  • Вирус или вредоносное ПО, повредившее файл core.data.dll.
  • Отказ оборудования Xactware, например, некачественный жесткий диск, вызвавший повреждение файла core.data.dll.
  • Другая программа изменила требуемую версию core.data.dll.
  • Другая программа злонамеренно или по ошибке удалила файл core.data.dll.
  • Другая программа удалила файл core.data.dll.

Как исправить ошибки в Core.data.dll

Предупреждение: Мы не рекомендуем скачивать core.data.dll с сайтов типа «DLL». Такие сайты распространяют файлы DLL, которые не одобрены официальным разработчиком файла core.data.dll и часто могут поставляться в комплекте с инфицированными вирусом или другими вредоносными файлами. Если вам требуется копия файла core.data.dll, настоятельно рекомендуется получить ее непосредственно у Xactware.

Ниже описана последовательность действий по устранению ошибок, призванная решить проблемы core.data.dll. Данная последовательность приведена в порядке от простого к сложному и от менее затратного по времени к более затратному, поэтому мы настоятельно рекомендуем следовать данной инструкции по порядку, чтобы избежать ненужных затрат времени и усилий.

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

Шаг 1: Зарегистрировать Core.data.dll вручную при помощи сервера регистрации Microsoft

При установке программного обеспечения, которое использует зависимости core.data.dll, это программное обеспечение должно автоматически зарегистрировать этот файл. В некоторых случаях файл DLL может быть не зарегистрирован соответствующим образом, что в результате приведет к ошибке «core.data.dll не зарегистрирован». К счастью, вы всегда можете воспользоваться встроенной утилитой под названием «Сервер регистрации Microsoft» (regsvr32.exe), чтобы заново зарегистрировать файл core.data.dll.

Как заново зарегистрировать core.data.dll из привилегированной командной строки (Windows XP, Vista, 7, 8 и 10):

  1. Нажмите на кнопку Начать.
  2. Введите «command» в строке поиска. ПОКА НЕ НАЖИМАЙТЕENTER!
  3. Удерживая клавиши CTRL-Shift на клавиатуре, нажмите ENTER.
  4. Будет выведено диалоговое окно для доступа.
  5. Нажмите Да.
  6. Введите следующую команду: regsvr32 /u core.data.dll.
  7. Нажмите ENTER. Для файла будет ОТМЕНЕНА РЕГИСТРАЦИЯ.
  8. Введите следующую команду: regsvr32 /i core.data.dll.
  9. Нажмите ENTER. Файл будет ЗАРЕГИСТРИРОВАН ЗАНОВО.
  10. Закройте окно командной строки.
  11. Перезапустить программу, связанную с ошибкой core.data.dll.

Шаг 2: Исправить ошибочные записи реестра для Core.data.dll

Иногда ошибки core.data.dll и другие системные ошибки DLL могут быть связаны с проблемами в реестре Windows. Несколько программ может использовать файл core.data.dll, но когда эти программы удалены или изменены, иногда остаются «осиротевшие» (ошибочные) записи реестра DLL.

В принципе, это означает, что в то время как фактическая путь к файлу мог быть изменен, его неправильное бывшее расположение до сих пор записано в реестре Windows. Когда Windows пытается найти файл по этой некорректной ссылке (на расположение файлов на вашем компьютере), может возникнуть ошибка core.data.dll. Кроме того, заражение вредоносным ПО могло повредить записи реестра, связанные с Xactimate. Таким образом, эти поврежденные записи реестра DLL необходимо исправить, чтобы устранить проблему в корне.

Редактирование реестра Windows вручную с целью удаления содержащих ошибки ключей core.data.dll не рекомендуется, если вы не являетесь специалистом по обслуживанию ПК. Ошибки, допущенные при редактировании реестра, могут привести к неработоспособности вашего ПК и нанести непоправимый ущерб вашей операционной системе. На самом деле, даже одна запятая, поставленная не в том месте, может воспрепятствовать загрузке компьютера!

В связи с подобным риском мы настоятельно рекомендуем использовать надежные инструменты очистки реестра, такие как WinThruster (разработанный Microsoft Gold Certified Partner), чтобы просканировать и исправить любые проблемы, связанные с core.data.dll. Используя очистку реестра, вы сможете автоматизировать процесс поиска поврежденных записей реестра, ссылок на отсутствующие файлы (например, вызывающих ошибку core.data.dll) и нерабочих ссылок внутри реестра. Перед каждым сканированием автоматически создается резервная копия, позволяющая отменить любые изменения одним кликом и защищающая вас от возможного повреждения компьютера. Самое приятное, что устранение ошибок реестра может резко повысить скорость и производительность системы.

Предупреждение: Если вы не являетесь опытным пользователем ПК, мы НЕ рекомендуем редактирование реестра Windows вручную. Некорректное использование Редактора реестра может привести к серьезным проблемам и потребовать переустановки Windows. Мы не гарантируем, что неполадки, являющиеся результатом неправильного использования Редактора реестра, могут быть устранены. Вы пользуетесь Редактором реестра на свой страх и риск.

Перед тем, как вручную восстанавливать реестр Windows, необходимо создать резервную копию, экспортировав часть реестра, связанную с core.data.dll (например, Xactimate):

  1. Нажмите на кнопку Начать.
  2. Введите «command» в строке поиска. ПОКА НЕ НАЖИМАЙТЕENTER!
  3. Удерживая клавиши CTRL-Shift на клавиатуре, нажмите ENTER.
  4. Будет выведено диалоговое окно для доступа.
  5. Нажмите Да.
  6. Черный ящик открывается мигающим курсором.
  7. Введите «regedit» и нажмите ENTER.
  8. В Редакторе реестра выберите ключ, связанный с core.data.dll (например, Xactimate), для которого требуется создать резервную копию.
  9. В меню Файл выберите Экспорт.
  10. В списке Сохранить в выберите папку, в которую вы хотите сохранить резервную копию ключа Xactimate.
  11. В поле Имя файла введите название файла резервной копии, например «Xactimate резервная копия».
  12. Убедитесь, что в поле Диапазон экспорта выбрано значение Выбранная ветвь.
  13. Нажмите Сохранить.
  14. Файл будет сохранен с расширением .reg.
  15. Теперь у вас есть резервная копия записи реестра, связанной с core.data.dll.

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

Мы не несем никакой ответственности за результаты действий, совершенных по инструкции, приведенной ниже — вы выполняете эти задачи на свой ​​страх и риск.

Шаг 3: Удалить или восстановить файл Core.data.dll из Корзины Windows

  1. Просто дважды щелкните по значку Корзина.
  2. В верхнем правом углу найдите core.data.dll.
  3. Если файл core.data.dll присутствует в результатах поиска, выберите его и переместите в следующую папку:
    1. Windows 95/98/Me = %PROGRAMFILES%\Xactware\Xactimate27\CORE
    2. Windows NT/2000 = %PROGRAMFILES%\Xactware\Xactimate27\CORE
    3. Windows XP, Vista, 7, 8, 10 = %PROGRAMFILES%\Xactware\Xactimate27\CORE
    4. 64-bit Windows = %PROGRAMFILES%\Xactware\Xactimate27\CORE
  4. После перемещения файла core.data.dll перезагрузите компьютер.

Tip: If you are positive that you deleted the core.data.dll file AND emptied the Recycle Bin, then you will need to use a file recovery program to restore the core.data.dll file. Click here to download a highly recommended file recovery program.


Шаг 4: Проведите полное сканирование вашего компьютера на вредоносное ПО

Есть вероятность, что ошибка core.data.dll может быть связана с заражением вашего компьютера вредоносным ПО. Эти вредоносные злоумышленники могут повредить или даже удалить файлы, связанные с DLL. Кроме того, существует возможность, что ошибка core.data.dll связана с компонентом самой вредоносной программы.

Совет: Если у вас еще не установлены средства для защиты от вредоносного ПО, мы настоятельно рекомендуем использовать Emsisoft Anti-Malware (скачать). В отличие от других защитных программ, данная программа предлагает гарантию удаления вредоносного ПО.

Шаг 5: Обновите драйверы устройств на вашем компьютере

Ошибки Core.data.dll могут быть связаны с повреждением или устареванием драйверов устройств. Драйверы с легкостью могут работать сегодня и перестать работать завтра по целому ряду причин. Хорошая новость состоит в том, что чаще всего вы можете обновить драйверы устройства, чтобы устранить проблему с DLL.

В связи с временными затратами и общей сложностью обновления драйверов мы настоятельно рекомендуем использовать утилиту обновления драйверов, например DriverDoc (разработана Microsoft Gold Partner), для автоматизации этого процесса.

Пожалуйста, учтите: Ваш файл core.data.dll может и не быть связан с проблемами в драйверах устройств, но всегда полезно убедиться, что на вашем компьютере установлены новейшие версии драйверов оборудования, чтобы максимизировать производительность вашего ПК.

Шаг 6: Используйте Восстановление системы Windows, чтобы «Отменить» последние изменения в системе

Восстановление системы Windows позволяет вашему компьютеру «отправиться в прошлое», чтобы исправить проблемы core.data.dll. Восстановление системы может вернуть системные файлы и программы на вашем компьютере к тому времени, когда все работало нормально. Это потенциально может помочь вам избежать головной боли от устранения ошибок, связанных с DLL.

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

Чтобы использовать Восстановление системы (Windows XP, Vista, 7, 8 и 10):

  1. Нажмите на кнопку Начать.
  2. В строке поиска введите «Восстановление системы» и нажмите ENTER.
  3. В окне результатов нажмите Восстановление системы.
  4. Введите пароль администратора (при появлении запроса).
  5. Следуйте инструкциям Мастера для выбора точки восстановления.
  6. Восстановить ваш компьютер.

Шаг 7: Удалите и установите заново программу Xactimate, связанную с Core.data.dll

Инструкции для Windows 7 и Windows Vista:

  1. Откройте «Программы и компоненты», нажав на кнопку Пуск.
  2. Нажмите Панель управления в меню справа.
  3. Нажмите Программы.
  4. Нажмите Программы и компоненты.
  5. Найдите Xactimate в столбце Имя.
  6. Нажмите на запись Xactimate.
  7. Нажмите на кнопку Удалить в верхней ленте меню.
  8. Следуйте инструкциям на экране для завершения удаления Xactimate.

Инструкции для Windows XP:

  1. Откройте «Программы и компоненты», нажав на кнопку Пуск.
  2. Нажмите Панель управления.
  3. Нажмите Установка и удаление программ.
  4. Найдите Xactimate в списке Установленные программы.
  5. Нажмите на запись Xactimate.
  6. Нажмите на кнопку Удалить справа.
  7. Следуйте инструкциям на экране для завершения удаления Xactimate.

Инструкции для Windows 8:

  1. Установите указатель мыши в левой нижней части экрана для показа изображения меню Пуск.
  2. Щелкните правой кнопкой мыши для вызова Контекстного меню Пуск.
  3. Нажмите Программы и компоненты.
  4. Найдите Xactimate в столбце Имя.
  5. Нажмите на запись Xactimate.
  6. Нажмите Удалить/изменить в верхней ленте меню.
  7. Следуйте инструкциям на экране для завершения удаления Xactimate.

После того, как вы успешно удалили программу, связанную с core.data.dll (например, Xactimate), заново установите данную программу, следуя инструкции Xactware.

Совет: Если вы абсолютно уверены, что ошибка DLL связана с определенной программой Xactware, удаление и повторная установка программы, связанной с core.data.dll с большой вероятностью решит вашу проблему.

Шаг 8: Запустите проверку системных файлов Windows («sfc /scannow»)

Проверка системных файлов — важная утилита, включенная в состав Windows. Она позволяет сканировать файлы на наличие повреждений и восстанавливать системные файлы Windows, такие как core.data.dll. Если утилита проверки системных файлов обнаружила проблему в core.data.dll или другом важном системном файле, она предпримет попытку заменить проблемные файлы автоматически, используя Кэш DLL (%WinDir%\System32\Dllcache\). Если файл core.data.dll отсутствует в Кэше DLL, или Кэш DLL поврежден, утилита предложит вставить установочный диск Windows для восстановления оригинальных файлов.

Чтобы запустить проверку системных файлов (Windows XP, Vista, 7, 8 и 10):

  1. Нажмите на кнопку Начать.
  2. Введите «command» в строке поиска. ПОКА НЕ НАЖИМАЙТЕENTER!
  3. Удерживая клавиши CTRL-Shift на клавиатуре, нажмите ENTER.
  4. Будет выведено диалоговое окно для доступа.
  5. Нажмите Да.
  6. Черный ящик открывается мигающим курсором.
  7. Введите «sfc /scannow» и нажмите ENTER.
  8. Проверка системных файлов начнет сканирование на наличие проблем core.data.dll и других системных файлов (проявите терпение — проверка может занять длительное время).
  9. Следуйте командам на экране.

Шаг 9: Установите все доступные обновления Windows

Microsoft постоянно обновляет и улучшает системные файлы Windows, связанные с core.data.dll. Иногда для решения проблемы DLL нужно просто напросто обновить Windows при помощи последнего пакета обновлений или другого патча, которые Microsoft выпускает на постоянной основе.

Чтобы проверить наличие обновлений Windows (Windows XP, Vista, 7, 8 и 10):

  1. Нажмите на кнопку Начать.
  2. Введите «update» в строке поиска и нажмите ENTER.
  3. Будет открыто диалоговое окно Обновление Windows.
  4. Если имеются доступные обновления, нажмите на кнопку Установить обновления.

Шаг 10: Произведите чистую установку Windows

Предупреждение: Мы должны подчеркнуть, что переустановка Windows займет очень много времени и является слишком сложной задачей, чтобы решить проблемы core.data.dll. Во избежание потери данных вы должны быть уверены, что вы создали резервные копии всех важных документов, изображений, программ установки программного обеспечения и других персональных данных перед началом процесса. Если вы сейчас е создаете резервные копии данных, вам стоит немедленно заняться этим (скачать рекомендованное решение для резервного копирования), чтобы защитить себя от безвозвратной потери данных.

Пожалуйста, учтите: Если проблема core.data.dll не устранена после чистой установки Windows, это означает, что проблема DLL ОБЯЗАТЕЛЬНО связана с аппаратным обеспечением. В таком случае, вам, вероятно, придется заменить соответствующее оборудование, вызывающее ошибку core.data.dll.

Имя файла: core.data.dll Последняя известная версия: 27.3.1088.23556
Разработчик: Xactware Размер файла (байтов): 663552
Программное обеспечение: Xactimate Операционная система: Windows Vista
Описание: Xactimate
MD5: 58698c676d8dc0e8597463fb84a56c06
SHA1: ab0c2d6a66c8a0c17cb43880eb4e9daee227006b
SHA256: 8fbb2bab77b7889af273467fa1af79a6cf8740e7d65329ff2c932d02d79cf597

Информация об операционной системе

Сообщения об ошибках Core.data.dll могут появляться в любых из нижеперечисленных операционных систем Microsoft Windows:

  • Windows 10
  • Windows 8
  • Windows 7
  • Windows Vista
  • Windows XP
  • Windows ME
  • Windows 2000

Проблема с Core.data.dll все еще не устранена?

Обращайтесь к нам в любое время в социальных сетях для получения дополнительной помощи:

Об авторе: Джей Гитер (Jay Geater) является президентом и генеральным директором корпорации Solvusoft — глобальной компании, занимающейся программным обеспечением и уделяющей основное внимание новаторским сервисным программам. Он всю жизнь страстно увлекался компьютерами и любит все, связанное с компьютерами, программным обеспечением и новыми технологиями.

Отобразить файлы DLL в алфавитном порядке:

Вы загружаете пробное программное обеспечение. Подписка на один год стоимостью $39,95 необходима для разблокировки всех функций приложения. Подписка обновляется автоматически по завершению (Узнать больше). Нажав на кнопку «Начать загрузку» и установив «Софт»», я подтверждаю, что прочитал(а) и согласен(на) с Пользовательским соглашением и Политикой конфиденциальности Solvusoft.

Core Data

Persist or cache data and support undo on a single device.

Overview

Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device.

Through Core Data’s Data Model editor, you define your data’s types and relationships, and generate respective class definitions. Core Data can then manage object instances at runtime to provide the following features.

Persistence

Core Data abstracts the details of mapping your objects to a store, making it easy to save data from Swift and Objective-C without administering a database directly.

Undo and Redo of Individual or Batched Changes

Core Data’s undo manager tracks changes and can roll them back individually, in groups, or all at once, making it easy to add undo and redo support to your app.

Background Data Tasks

Perform potentially UI-blocking data tasks, like parsing JSON into objects, in the background. You can then cache or store the results to reduce server roundtrips.

View Synchronization

Core Data also helps keep your views and data synchronized by providing data sources for table and collection views.

Versioning and Migration

Core Data includes mechanisms for versioning your data model and migrating user data as your app evolves.

Core Data / 1.1. Основы Core Data

Футбол состоит из побед и поражений, главное — не останавливаться из-за трудностей.

В этом уроке


  • Стэк Core Data
  • Модель данных
  • Свойства моделей
  • Добавления новых объектов в контекст

Зачем нужна Core Data?

Раньше мы видели множество способов для хранения данных — текстовые файлы, plist, xml, json. Но все они имеют множество недостатков для хранения на устройстве пользователя, начиная от рутины по обработке и заканчивая низкой производительностью для больших объемов данных.

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

Есть несколько основных вариантов баз данных — SQL или реляционные (хотя понятия несинонимичны, они часто существуют бок-о-бок), NoSQL и базы данных на основе графов. Каждая из них имеет свои особенности и цели применения — нельзя сказать, что какая-то из них лучше другой (если говорить о конкретных продуктах, то старайтесь избегать поделки Microsoft под названием MS SQL Server).

В основе хранения данных на устройстве пользователя лежит SQLite-база данных. Она специально предназначена для интеграции в приложения и единичное использование — при оперировании ею с помощью Core Data доступ к базе данных будет иметь только Ваше приложение, размещаться она будет в папке Library песочницы, куда у пользователя нет доступа.

Core Data и Вы

Мы создадим приложение для списка дел — мы сильно упростим его по сравнению с изначальным вариантом, который мы уже делали и сохраняли данные на диск кустарными методами.

  • Создайте новое Single View приложение, при этом галочку у Core Data мы всё равно ставить не будем — мы должны понять как всё это работает самостоятельно, а готовый вариант лишь затруднит написание кода с нуля.

До iOS 10 пользователям приходилось работать напрямую со стэком Core Data — такая возможность имеется и сейчас, если Вам нужен больший контроль над всем этим, однако все элементы теперь объединены в очень удобную штучку — Persistent Container .

В AppDelegate мы добавим два удобных метода для извлечения контейнера данных:

Казалось бы — очень простой метод. И что же может пойти не так? Ответ прост — почти всё:

  • Родительская директория не существует, не может быть создана или запрещает запись (наиболее вероятная проблема для macOS)
  • Хранилище недоступно из-за разрешений пользователя, или так как устройство заблокировано (устройства Apple умеют при блокировке, оставаясь включенными блокировать доступ к данным, чтобы люди не могли их извлечь методами пещерных людей (молоток и отвертка)
  • Отсутствует свободное место для контейнера
  • Хранилище не может быть мигрировано до последней версии модели (про миграции мы расскажем чуть позже)

В полифункциональных приложениях Вы вероятно захотите вынести функционал данных в отдельный сервис-класс.

Следующий метод позволит сохранить контекст в контейнер:

Этот метод может сломаться по тем же причинам.

Модель данных

  1. Нажмите CMD + N для создания нового файла
  2. Найдите секцию Core Data
  3. Выберите Data Model В качестве названия укажите SWCoreData1 , что позволит приложению загружать модель.

Теперь перейдите в этот файл в инспекторе файлов:

В первое знакомство это окно может вызвать чувство страха.

Core Data умеет работать не только с базами данных, но и создавать хранилища в памяти, писать в XML (только на macOS), а также в бинарный формат. До тех пор, пока не поймёте, что Вы не решите проблему без указанных вещей — не используйте их.

Нажмите по плюсу у Add Entity. Это создаст новую запись в системе — запись можно считать эквивалентной классу, только с тем исключением, что она лежит в системе контроля данных, а управлять ей могут совсем другие классы (скорее всего Вам не придётся так извращаться).

Дайте ей название List — это будет список дел.

В центральной панели у нас есть 3 большие секции:

  • Attributes — Атрибуты модели — схожи со свойствами объектов
  • Relationships — Отношения между моделями
  • Fetched Properties — специальные слабые отношения, которые позволяют подтягивать другие отношения в виде запроса — иногда они могут сильно Вас запутать, потому при необходимости не используйте их часто.

Давайте добавим атрибут name типа String в модель.
Есть множество типов данных для модели, которые прозрачно превращаются в те, что заложены в SQLite .

Заметьте, что здесь нет простого типа Int — в Objective-C он является примитивом, а числовые типы выражаются через знакомый нам NSNumber.

Справа нам доступен новый инспектор для моделей:

  • Properties — Вы можете сделать свойство опциональным (по-умолчанию все свойства такие) или же переходным transient — такое свойство, хоть и управляется Core Data, не хранится в базе данных. Эти два пункта нельзя сочетать вместе. Уберите опциональность у имени списка дел.
  • Следующий блок посвящён валидации поля — он меняет в зависимости от атрибута — для строки можно задать минимальную, максимальную длины, значение по-умолчанию и регулярное выражение, которому должна соответствовать строка. Нам важно, чтобы нельзя было давать слишком короткие названия — менее 4 символов.
  • Блок UserInfo позволяет добавить к модели атрибуты, подставляемые во время выполнения.

Теперь Выберите сам класс целиком:

  • Abstract Entity — Можно сделать запись абстрактной, тогда она будет использоваться для создания других записей, но её объекты не будут созданы, ровно как и записаны на диск
  • Parent Entity Классы в Core Data можно строить друг на основе друга — но наследование таких классов отличается от обычного — они будут жить в одной таблице в базе данных, при этом иметь общими полями все, что есть у всех моделей, просто они будут принимать нулевые значения. Потому наследуйте записи только при крайней необходимости, иначе столкнётесь с проблемой разреженных баз данных — когда таблицы будут иметь большое число NULL-значения.

NULL — это аналог nil в мире баз данных, показывающий что какого-то значения нет.

Мы хотим показать, что происходит у неё под юбкой, а потому выберем ручное создание класса. Теперь Выберите класс и нажмите в верхнем меню Editor -> Create NSManagedObject Subclass.

Давайте посмотрим содержание двух файлов:

NSManagedObject — это специальный наследник NSObject , который позволяет объекту жить не просто в рантайме objc, но и в среде Core Data, которая управляет его поведением — такому объекту не нужно реализовывать многие свои методы и свойства — они будут добавлены на лету.

На данный момент кодогенерация даёт нам следующий второй файл:

И здесь для нас много нового — первый метод класса позволяет конструировать запросы к этому классу в базе данных, при этом он не экспортируется в objc — в ней уже есть метод с таким же названием, который не специализируется конкретным типом и возвращает голый объект, а в этом варианте C недоступна перегрузка функций.

Второй интересный момент — атрибут @NSManaged , который говорит системе, что это свойство управляется Core Data и будет добавлено на лету, а потому за него можно не волноваться.

Заметьте, что имя сгенерировалось опционалом (в большинстве случаев) — нам просто нужно убрать знак вопроса у строки. Это известное поведение кодогенерации и остаётся лишь надеяться, что его исправят.

И хотя Core Data использует в большинстве случаев под собой базы данных — она не является базой данных или системой управления баз данных. База данных SQLite лишь выступает хранилищем для объектов Core Data. Core Data — это граф объектов в памяти с их отношениями и свойствами. То, как он будет существовать в том или ином месте — решать Core Data. Думайте о ней как об ещё одном способе сохранения объектов. Для обычных SQL баз данных хорошим способом оптимизации выступает нормализация таблиц, но здесь она может вызвать обратный эффект.

Скелет приложения

Теперь необходимо создать скелет приложения, чтобы мы могли продемонстрировать Вам весь функционал Core Data.

  1. Встройте наш единственный контроллер в контроллер навигации
  2. Задайте ему заголовок To Do Lists
  3. Поместите на него табличное представление:
    • Задайте ему нулевые отступы от границ
    • Делегат и источник данных — контроллер
    • Аутлет tableView
  4. В таблице сделайте одну динамическую ячейку:
    • Стиль — с подзаголовком
    • Индикатор detail
    • Идентификатор ListCell

В его файле создадим несколько свойств для удобства:

В реальном приложении их лучше вынести в стек Core Data

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

Реализуйте протоколы источника и делегата табличного представления (делегат пока что будет пуст, а ячейка в качестве заголовка должна содержать название списка дел):


Теперь пропишем одну специальную функцию, которая будет создавать запросы по извлечению данных:

Извлечение объектов может провалится по множеству причин, потому его надо соответственно перехватить.

Теперь во viewDidLoad мы добавим извлечение контейнера, контекста и данных:

Добавление нового объекта в контекст

Все хорошо, но данных-то у нас нет и взяться им неоткуда. Создадим ещё одну форму для добавления списка дел.

Сперва создайте класс AddListTableViewController , унаследовав его от сами знаете чего. После его генерации удалите из него всю внутреннюю часть.

  1. На полотно перетащите Table View Controller
  2. Задайте ранее созданный класс
  3. На основном контролере создайте кнопку в правой части панели навигации со значком +
  4. От кнопки проведите show-сегвей к табличному контроллеру
  5. Задайте ему идентификатор ToAddList
  6. На том контроллере создайте кнопку Save с методом saveButtonPressed
  7. А заголовок Add List
  8. Переключите таблицу в статический режим
  9. Оставьте пока что лишь одну ячейку:
    1. Задайте ей высоту в 50 точек
    2. В неё поместите текстовое поле
    3. Его отступы должны быть нулевыми с учётом марджинов родительского представления
    4. Текст-заместитель — Name
    5. Аутлет — nameField

Для сохранения данных мы воспользуемся старым добрым методом с протоколом.

Создадим протокол для делегата в том же файле:

Теперь создайте слабое свойство-делегат:

А теперь закончим тело метода по сохранению объекта:

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

Первый пункт Вы можете сделать самостоятельно:

Второй же пункт несколько интереснее:

Каждый управляемый объект получает специальный конструктор для добавления в контекст, после чего нам нужно задать его свойства и сохранить контекст. Затем мы просто заново извлекаем данные.

Попробуйте создать свой список дел. Если же Вы зададите имя, меньшее 4 символов, то будет вызвана ошибка валидации примерно такого вида:

Лучшим поведением будет выдавать пользователю сообщения о проблемах валидации, а не ломать всё приложение при попытке сохранения данных.

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

Ограничения Core Data

Несмотря на всю свою красоту и мощь — Core Data очень слабо применима вне конечных приложений — её варианта нет для Linux-версии Swift, так как она построена поверх Objective-C и его элементов, а даже если бы она там и была — применять её для серверной части было бы неэффективно — SQLite хорошо подходит для лёгких приложений и встраиваемых систем, но не для поддержки больших сервисов.

coredatarecovery.ca не работает или есть другие проблемы с доступом?

Проверка текущего статуса Core Data Recovery уже запущена (14.11.2020).

Счетчик времени непрерывной работы coredatarecovery.ca

Разместите счетчик времени непрерывной работы coredatarecovery.ca на вашем сайте. Данный счетчик отображает процентное отношение удачных проверок к общему количеству проверок.

Что делать, если coredatarecovery.ca недоступен?

Если Core Data Recovery работает, но вы не можете получить доступ к странице, попробуйте одно из следующих решений:

Кэш браузера . Большинство браузеров использует кэширование страниц для сохранения часто запрашиваемых ресурсов на компьютере пользователя, что позволяет сократить потребление трафика и ускорить работу браузера. Чтобы получить актуальную версию страницы, игнорируя кэш, используйте комбинацию Ctrl + F5 .

Блокировка доступа к сайту . Если вы используете динамические IP-адреса при подключении к Интернету, возможно, доступ к сайту для вашего текущего IP-адреса ранее был заблокирован. Очистите файлы cookie и смените IP-адрес .

Антивирус и файрвол . Убедитесь, что антивирусные программы или файрвол установленные на ваш компьютер не блокируют доступ к coredatarecovery.ca.

DNS-кэш . DNS-кэш содержит в себе записи о сайтах, которые вы посещали. Если, например, сайт сменил свой IP-адрес, вы не сможете получить к нему доступ. Очистите DNS-кэш на вашем компьютере и повторите попытку.

Альтернативные службы DNS . DNS (Domain Name System) преобразует доменные имена в IP-адреса. Попробуйте использовать альтернативную службу DNS , отличную от вашего провайдера, например, OpenDNS или Google Public DNS.

Ошибки перенаправления на coredatarecovery.ca

Возможно, на сайте coredatarecovery.ca некорректно настроено перенаправление с разных версий. Воспользуйтесь ссылками ниже:
http://coredatarecovery.ca http://www.coredatarecovery.ca https://coredatarecovery.ca https://www.coredatarecovery.ca

Другая информация

Заголовок : Data Recovery — Canadian Hard Drive Recovery Services — CDR
Описание : Canadian data recovery service, More than 15 years experience in data restoration delivering our clients a unique high-contact customer focus service.

Coredata — проблемы с Core Data

Core Data Programming Guide

Troubleshooting Core Data

Core Data builds on functionality provided by other parts of Cocoa. When diagnosing a problem with an application that uses Core Data, take care to distinguish between problems that are specific to Core Data and those that stern from an error with another framework or that are architecture-related. Poor performance, for example, may not be a Core Data problem, but instead due to a failure to observe standard Cocoa techniques of memory management or resource conservation. If a user interface does not update properly, this may be due to an error in how you have configured Cocoa bindings.

Object Life Cycle Problems

Merge errors

Problem: You see the error message, » Could not merge changes .»

Cause: Two different managed object contexts tried to change the same data. This is also known as an optimistic locking failure.

Remedy: Either set a merge policy on the context, or manually (programmatically) resolve the failure. You can retrieve the currently committed values for an object using committedValuesForKeys: , and you can use refreshObject:mergeChanges: to refault the object, so that when it is next accessed, its data values are retrieved from its persistent store.

Assigning a managed object to a different store

Problem: You see an exception that looks similar to this example.

  1. [ _assignObject:toPersistentStore:]:
  2. Can’t reassign an object to a different store once it has been saved.

Cause: The object you are trying to assign to a store has already been assigned and saved to a different store.

Remedy: To move an object from one store to another, you must create a new instance, copy the information from the old object, save it to the appropriate store, and then delete the old instance.

Fault cannot be fulfilled

Problem: You see the error message, NSObjectInaccessibleException ; «Core Data could not fulfill a fault.»

Cause: The object that Core Data is trying to realize has been deleted from the persistent store.

Remedy: Discard this object by removing all references to it.

Details: This problem can occur in at least two situations:

You started with a strong reference to a managed object from another object in your application.

You deleted the managed object through the managed object context.

You saved changes on the object context.

At this point, the deleted object has been turned into a fault. It isn’t destroyed because doing so would violate the rules of memory management.

Core Data will try to realize the faulted managed object but will fail to do so because the object has been deleted from the store. That is, there is no longer an object with the same global ID in the store.

You deleted an object from a managed object context.

The deletion failed to break all relationships from other objects to the deleted object.


You saved changes.

At this point, if you try to fire the fault of a relationship from another object to the deleted object, it may fail, depending on the configuration of the relationship, which affects how the relationship is stored.

The delete rules for relationships affect relationships only from the source object to other objects (including inverses). Without potentially fetching large numbers of objects, possibly without reason, there is no way for Core Data to efficiently clean up the relationships to the object.

Keep in mind that a Core Data object graph is directional. That is, a relationship has a source and a destination. Following a source to a destination does not necessarily mean that there is an inverse relationship. So, in that sense, you need to ensure that you are properly maintaining the object graph across deletes.

Core Data uses inverse relationships to maintain referential integrity within the data model. If no inverse relationship exists and an object is deleted, you will be required to clean up that relationship manually.

In practice, a well-designed object graph does not require much manual post-deletion clean-up. Most object graphs have entry points that in effect act as a root node for navigating the graph, and most insertion and deletion events are rooted at those nodes just like fetches. This means that delete rules take care of most of the work for you. Similarly, because smart groups and other loosely coupled relationships are generally best implemented with fetched properties, various ancillary collections of entry points into the object graph generally do not need to be maintained across deletes, because fetched relationships have no notion of permanence when it comes to objects found through the fetched relationship.

Managed object inval > Problem: You see an exception that looks similar to this example:

  1. [ _assignObject:toPersistentStore:]:
  2. The NSManagedObject with ID:#### has been invalidated.

Cause: Either you have removed the store for the fault you are attempting to fire, or the managed object’s context has been sent a reset .

Remedy: Discard this object by removing all references to it. If you add the store again, you can try to fetch the object again.

> Problem: You see an exception that looks similar to the following example.

  1. [ valueForUndefinedKey:]:
  2. this class is not key value coding-compliant for the key randomKey.

Cause: Either you used an incorrect key, or you initialized your managed object with init instead of initWithEntity:insertIntoManagedObjectContext: .

Entity > Problem: You define an entity that uses a custom sub >NSManagedObject , then in code you create an instance of the entity and invoke a custom method, as illustrated in this code fragment:

  1. NSManagedObject * entityInstance = [ NSEntityDescription insertNewObjectForEntityForName: @»MyEntity» inManagedObjectContext: moc ];
  2. [ entityInstance setAttribute: newValue ];
  1. let entityInstance = NSEntityDescription . insertNewObjectForEntityForName ( «MyEntity» , inManagedObjectContext : moc )
  2. entityInstance . attribute = newValue

You get a runtime error like this:

  1. «2005-05-05 15:44:51.233 MyApp[1234] ***
  2. В В В В -[NSManagedObject setNameOfEntity:]: selector not recognized [self = 0x30e340]

Cause: In the model, you misspelled the name of the custom class for the entity.

Remedy: Ensure that the spelling of the custom class name in the model matches the spelling of the custom class you implement.

Custom accessor methods are not invoked, and key dependencies are not obeyed

Problem: You define a custom sub >NSManagedObject for a particular entity and implement custom accessors methods (and perhaps dependent keys). At runtime, the accessor methods are not called, and the dependent key is not updated.

Cause: In the model, you did not specify the custom class for the entity.

Remedy: Ensure that the model specifies the custom >NSManagedObject .

Problems with Fetching

SQLite store does not work with sorting

Problem: You create a sort descriptor that uses a comparison method defined by NSString, such as the following:

  1. NSSortDescriptor * mySortDescriptor = [[ NSSortDescriptor alloc ] initWithKey: @»lastName» ascending: YES selector: @selector ( localizedCaseInsensitiveCompare: )];
  1. let mySortDescriptor = NSSortDescriptor ( key : «lastName» , ascending : true , selector : #( localizedCaseInsensitiveCompare :))

You then either use this descriptor with a fetch request or as one of an array controller’s sort descriptors. At runtime, you see an error message that looks similar to the following:

  1. NSRunLoop ignoring exception ‘ unsupported NSSortDescriptor selector:
  2. В В В В В В В В localizedCaseInsensitiveCompare: ‘ that raised during posting of
  3. В В В В В В В В delayed perform with target 3e2 e42 and selector ‘ invokeWithTarget: ‘

Cause: Exactly how a fetch request is executed depends on the store—see Fetching Objects .

Remedy: If you are executing the fetch directly, do not use Cocoa-based sort operators—instead, sort the returned array in memory. If you are using an array controller, you may need to sub >NSArrayController , so that it will not pass the sort descriptors to the database but will instead do the sorting after your data has been fetched.

Problems with Saving

Cannot save documents because entity is null

Problem: You have a Core Data document-based application that is unable to save. When you try to save the document you get an exception:

  1. Exception raised during posting of notification. Ignored. exception: Cannot perform operation since entity with name ‘Wxyz’ cannot be found

Cause: This error is emitted by an instance of NSObjectController (or one of its subclasses) that is set in Entity mode but can’t access the entity description in the managed object model associated with the entity name specified in Interface Builder. In short, you have a controller in entity mode with an invalid entity name.

Remedy: Select in turn each of your controllers in Interface Builder, and press Command-1 to show the inspector. For each controller, ensure you have a valid entity name in the Entity name field at the top of the inspector.

Exception generated in retainedDataForObject > Problem: You add an object to a context. When you try to save the document you get an error that looks like this:

  1. [date] My App[2529:4b03] cannot find data for a temporary oid: 0x60797a0 x-coredata:///MyClass/t8BB18D3A-0495-4BBE-840F-AF0D92E549FA195>

This exception is in -[NSSQLCore retainedDataForObjectID:withContext:] , and the backtrace looks like this:

  1. #1 0x9599a6ac in -[NSSQLCore retainedDataForObjectID:withContext:]
  2. #2 0x95990238 in -[NSPersistentStoreCoordinator(_NSInternalMethods) _conflictsWithRowCacheForObject:andStore:]
  3. #3 0x95990548 in -[NSPersistentStoreCoordinator(_NSInternalMethods) _checkRequestForStore:originalRequest:andOptimisticLocking:]
  4. #4 0x9594e8f0 in -[NSPersistentStoreCoordinator(_NSInternalMethods) executeRequest:withContext:]
  5. #5 0x959617ec in -[NSManagedObjectContext save:]

The call to _conflictsWithRowCacheForObject: is comparing the object you’re trying to save with its last cached version from the database. Basically, it’s checking to see if any other code (thread, process, or just a different managed object context) changed this object without your knowledge.

Core Data does not do this check on newly inserted objects because they could not have existed in any other scope. They haven’t been written to the database yet.

Cause: You may have forced a newly inserted object to lose its inserted status and then changed or deleted it. This could happen if you passed a temporary object >objectWithID: . You may have passed an inserted object to another managed object context.

Remedy: There are a number of possible remedies, depending on the root cause:

Do not pass an inserted (not yet saved) object to another context. Only objects that have been saved can be passed between contexts.

Do not invoke refreshObject: on a newly-inserted object.

Do not make a relationship to an object that you never insert into the context.

Ensure that you use the designated initializer for instances of NSManagedObject .

Before you save (frame #5 in the stack trace), make sure that the context’s updatedObjects and deletedObjects sets should only have members whose object >NO false from isTemporaryID .

Debugging Fetching

Use the user default com.apple.CoreData.SQLDebug setting to log to stderr the actual SQL statement sent to SQLite. (Note that user default names are case sensitive.) For example, you can pass the following as an argument to the application:

  1. -com.apple.CoreData.SQLDebug 1

Higher levels of debug numbers produce more information, although using higher numbers is likely to be of diminishing utility.

The information the output prov >Preventing a Fault from Firing .

Using com.apple.CoreData.SQLDebug for reverse engineering to facilitate direct access to the SQLite file is not supported. It is exclusively a debugging tool.

As this is for debugging, the exact format of the logging is subject to change without notice. You should not, for example, pipe the output into an analysis tool with the expectation that it will work on all OS versions.

Managed Object Models

Your application generates the message «+entityForName: could not locate an NSManagedObjectModel»

Problem: The error states clearly the issue—the entity description cannot find a managed object model from which to access the entity information.

Cause: The model may not be included in your application resources. You may be trying to access the model before it has been loaded. The reference to the context may be nil .

Remedy: Be sure that the model is included in your application resources and that the corresponding project target option in Xcode is selected.

The class method you invoked requires an entity name and a managed object context, and it is through the context that the entity gets the model. Basically, the core data stack looks like:

managed object context — persistent store coordinator — managed object model

If the managed object model cannot be found, make sure of the following:

The managed object context is not nil .

If you are setting the reference to the context in a .nib file, make sure the appropriate outlet or binding is set correctly.

If you are managing your own Core Data stack, make sure that the managed object context has an associated coordinator ( setPersistentStoreCoordinator: ) after allocating.

The persistent store coordinator has a valid model.

Bindings Integration

Many problems relating to bindings are not specific to Core Data and are discussed in Troubleshooting Cocoa Bindings. This section describes some additional problems that could be caused by the interaction of Core Data and bindings.

Cannot access contents of an object controller after a nib is loaded

Problem: You want to perform an operation with the contents of an object controller (an instance of NSObjectController , NSArrayController , or NSTreeController ) after a .nib file has been loaded, but the controller’s content is nil .

Cause: The controller’s fetch is executed as a delayed operation performed after its managed object context is set (by nib loading)—the fetch therefore happens after awakeFromNib and windowControllerDidLoadNib: .

Cannot create new objects with array controller

Problem: You cannot create new objects using an NSArrayController . For example, when you click the button assigned to the add: action, you get an error similar to the following:

  1. 2005-05-05 12:00:)).000 MyApp[1234] *** NSRunLoop
  2. ignoring exception ‘Failed to create new object’ that raised
  3. during posting of delayed perform with target 123456
  4. and selector ‘invokeWithTarget:’

Cause: In your managed object model, you may have specified a custom class for the entity, but you have not implemented the class.

Remedy: Implement the custom >NSManagedObject .

A table view bound to an array controller doesn’t display the contents of a relationship

Problem: You want to display the contents of a relationship in a table view bound to an array controller, but nothing is displayed and you get an error similar to the following:

  1. 2005-05-27 14:13:39.077 MyApp[1234] *** NSRunLoop ignoring exception
  2. ‘Cannot create NSArray from object ()
  3. of class _NSFaultingMutableSet — consider using contentSet
  4. binding instead of contentArray binding’ that raised during posting of
  5. delayed perform with target 385350 and selector ‘invokeWithTarget:’

Cause: You bound the controller’s contentArray binding to a relationship. Relationships are represented by sets.

Remedy: Bind the controller’s contentSet binding to the relationship.

A new object is not added to the relationship of the object currently selected in a table view

Problem: You have a table view that displays a collection of instances of an entity. The entity has a relationship to another entity, instances of which are displayed in a second table view. Each table view is managed by an array controller. When you add new instances of the second entity, they are not added to the relationship of the currently selected instance of the first.

Cause: The two array controllers are not related. There is nothing to tell the second array controller about the first.

Remedy: Bind the second array controller’s contentSet binding to the key path that specifies the relationship of the selection in the first array controller. For example, if the first array controller manages the Department entity, and the second array controller manages the Employee entity, then the contentSet binding of the second array controller should be [Department Controller].selection.employees .

Table view or outline view contents not kept up-to-date when bound to an NSArrayController or NSTreeController object

Problem: You have a table view or outline view that displays a collection of instances of an entity. As new instances of the entity are added and removed, the table view is not kept in sync.

Cause: If the controller’s content is an array that you manage yourself, then it is possible you are not modifying the array in a way that is KVO-compliant.

If the controller’s content is fetched automatically, then you have probably not set the controller to «Automatically prepare content.»

Alternatively, the controller may not be properly configured.

Remedy: If the controller’s content is a collection that you manage yourself, then ensure you modify the collection in a way that is KVO-compliant. See Troubleshooting Cocoa Bindings.

If the controller’s content is fetched automatically, set the «Automatically prepares content» switch for the controller in the Attributes inspector in Interface Builder (see also automaticallyPreparesContent ). Doing so means that the controller will track inserts into and deletions from its managed object context for its entity.

Also check to see that the controller is properly configured (for example, that you have set the entity correctly).

Цукерберг рекомендует:  Реверсинг и обфускация, как это работает
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих