Я обычно рекомендую один из двух подходов. (Существуют и другие настройки, которые работают, но это две, которые я использовал, протестировал и рекомендую.)
Простой путь
Вы читаете из viewContext и пишете в viewContext и используете только основной поток. Это самый простой подход, позволяющий избежать многих многопоточных проблем, характерных для основных данных. Проблема в том, что доступ к диску происходит в главном потоке, и если вы делаете это много, это может замедлить работу вашего приложения.
Этот подход подходит для небольших легких приложений. Хорошим кандидатом для этого может быть любое приложение, в котором всего сущностей меньше, чем несколько тысяч объектов и нет массовых изменений одновременно. Хороший пример - простой список задач.
Сложный Путь
Сложный способ - читать только из viewContext в главном потоке и выполнять все ваши записи, используя executeBackgroundTask внутри последовательной очереди. Каждый блок в executeBackgroundTask перезагружает все необходимые управляемые объекты (используя objectIds), а все создаваемые управляемые объекты отбрасываются в конце блока. Каждый executeBackgroundTask является транзакционным, и saveContext вызывается в конце блока.
Это надежная и функциональная настройка основных данных, которая может управлять данными в любом разумном масштабе.
Проблема в том, что вы всегда должны быть уверены, что управляемые объекты находятся в ожидаемом контексте и доступны в правильном потоке. Вам также нужна последовательная очередь, чтобы избежать конфликтов записи. И вам часто нужно использовать fetchedResultsController, чтобы убедиться, что объекты не удаляются, пока вы держите на них указатели.