Core Data для iOS. Глава №2. Практическая часть

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



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



    Вступление

    Будем мы создавать вот такую модель:
    image

    Затем добавим несколько записей и запросим их. Вывод будет производиться в консоль, чтобы мы не задавались еще и вопросами визуальными.
    Готовы? Тогда поехали!

    Описание

    Будем создавать объектный граф нашего любимого ресурса — Хабра.
    Есть N основных объектов:
    • Запись в блоге
    • Пользователь
    • Теги
    • Хабы
    • Вопросы
    • Ответы
    • Учетная запись компании

    Этого будет достаточно.

    Какие данные содержит каждый из объектов?
    • Запись в блоге — заголовок, текст
    • Пользователь — ник, карма, рейтинг, пол, аватар, почтовый ящик
    • Тег — наименование
    • Хаб — наименование, профильный ли хаб
    • Вопрос — заголовок, текст
    • Ответ — текст
    • Учетная запись компании — наименование организации, рейтинг


    Приступаем к работе

    Открываем XCode и создаём новый проект Single View Application:


    Вводим наименование проекта, префиксы и прочее:
    image

    Знакомое окно:
    image

    Добавляем Core Data

    Добавляем Core Data Framework в проект:
    image

    Создаем модели

    Добавить новый файл -> iOS -> CoreData -> Data Model
    image
    image

    Начнём с записи в блоге.
    Создаем новую сущность и называем её Blogpost, добавляем два атрибута caption (String) и text (String).
    image

    Создаем новую сущность и называем её User, добавляем атрибуты avatar (String), email (String), gender (Decimal), karma (Integer 16), nickname (String), rating (Integer 16).
    image

    Создаем новую сущность и называем её Tag, добавляем всего один атрибут name (String).
    image

    Создаем новую сущность и называем её Hab, добавляем два атрибута name (String), target (Boolean).
    image

    Создаем новую сущность и называем её Question, добавляем два атрибута caption (String), text (String).
    image

    Создаем новую сущность и называем её Response, добавляем один атрибут text (String).
    image

    Создаем новую сущность и называем её Organization, добавляем два атрибута name (String), rating (Integer 16).
    image

    Вот что у нас есть в итоге:
    image

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

    Начнем с построение связи «учетная запись компании» (один-ко-многим) «пользователи».
    Выбираем из списка сущностей Organization и добавляем новую связь нажав на "+" в разделе Relationships:
    image

    Так как по умолчанию XCode создаёт связь один-к-одному мы должны изменить тип связи:
    image

    Теперь у каждой организации есть множество пользователей. Поле Inverse (обратная связь) мы сейчас тоже установим, но предварительно добавим новую связь в сущность Пользователя и назовем её organization (организация в которой работает пользователь, а если он не работает нигде, то поле будет null):
    image

    Теперь вновь откроем редактирование сущности Organization и установим поле Inverse в organization:
    image

    Вот как стал выглядеть теперь объектный граф:
    image

    Попробуйте расставить остальные связи сами, а затем сверьте с тем, что у меня получилось.
    Вы знаете как создать связь, вы знаете как изменить тип связи с один-к-одному на один-ко-многим — этого будет достаточно.
    Итоговая картина:
    image

    Создаем организацию

    Уже имеем в AppDelegate.h такое:
    //
    //  TMAppDelegate.h
    //  Habrahabr
    //
    //  Created by AndrewShmig on 8/31/13.
    //  Copyright (c) 2013 TM. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import <CoreData/CoreData.h>
    
    @class TMViewController;
    
    @interface TMAppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    @property (strong, nonatomic) TMViewController *viewController;
    
    @property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
    
    @end
    

    И в AppDelegate.m:
    //
    //  TMAppDelegate.m
    //  Habrahabr
    //
    //  Created by AndrewShmig on 8/31/13.
    //  Copyright (c) 2013 TM. All rights reserved.
    //
    
    #import "TMAppDelegate.h"
    
    @implementation TMAppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        return YES;
    }
    
    #pragma mark - Core Data Stack
    
    - (NSManagedObjectModel *)managedObjectModel
    {
        if(nil != _managedObjectModel)
            return _managedObjectModel;
        
        _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
        
        return _managedObjectModel;
    }
    
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
        if(nil != _persistentStoreCoordinator)
            return _persistentStoreCoordinator;
        
        NSURL *storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
                                                                   inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:@"Habrahabr.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();
        }
        
        return _persistentStoreCoordinator;
    }
    
    - (NSManagedObjectContext *)managedObjectContext
    {
        if(nil != _managedObjectContext)
            return _managedObjectContext;
        
        NSPersistentStoreCoordinator *store = self.persistentStoreCoordinator;
        if(nil != store){
            _managedObjectContext = [[NSManagedObjectContext alloc] init];
            [_managedObjectContext setPersistentStoreCoordinator:store];
        }
        
        return _managedObjectContext;
    }
    
    @end
    

    Перепишем метод application:didFinishLaunchingWithOptions: таким образом:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    //    Создаем организацию
        NSManagedObject *yandex = [NSEntityDescription insertNewObjectForEntityForName:@"Organization"
                                                                inManagedObjectContext:self.managedObjectContext];
        [yandex setValue:@"Yandex Inc." forKey:@"name"];
        [yandex setValue:@672 forKey:@"rating"];
        
    //    создаем сотрудников Yandex
        NSManagedObject *pupkin = [NSEntityDescription insertNewObjectForEntityForName:@"User"
                                                                inManagedObjectContext:self.managedObjectContext];
        [pupkin setValue:@"VaseaPup" forKey:@"nickname"];
        [pupkin setValue:@"vasilisa@yandex.ru" forKey:@"email"];
        [pupkin setValue:@1 forKey:@"gender"]; // 0 - unknown, 1 - male, 2 - female
        [pupkin setValue:@0 forKey:@"karma"];
        [pupkin setValue:@0 forKey:@"rating"];
        
        NSManagedObject *gosha = [NSEntityDescription insertNewObjectForEntityForName:@"User"
                                                               inManagedObjectContext:self.managedObjectContext];
        [gosha setValue:@"Goshka" forKey:@"nickname"];
        [gosha setValue:@"gosha.k@yandex.ru" forKey:@"email"];
        [gosha setValue:@0 forKey:@"gender"];
        [gosha setValue:@0 forKey:@"karma"];
        [gosha setValue:@0 forKey:@"rating"];
        
    //    связываем сотрудников с компанией
        NSMutableSet *employees = [yandex mutableSetValueForKey:@"employees"];
        [employees addObject:pupkin];
        [employees addObject:gosha];
        
    //    сохраняем данные в хранилище
        [self saveContext];
        
        NSLog(@"Finish!");
        
        return YES;
    }
    

    Запустим приложение. Данные должны были быть сохранены. Проверим это.
    Найдем файл Habrahabr.sqlite:
    image

    Запустим терминал и проверим структуру БД:
    AndrewShmigs-MacBook-Pro:~ new$ cd "/Users/new/Library/Application Support/iPhone Simulator/6.1/Applications/95B0716A-9C2C-4BD8-8117-62FB46BB5879"
    AndrewShmigs-MacBook-Pro:95B0716A-9C2C-4BD8-8117-62FB46BB5879 new$ ls
    Documents	Habrahabr.app	Library		tmp
    AndrewShmigs-MacBook-Pro:95B0716A-9C2C-4BD8-8117-62FB46BB5879 new$ cd Documents/
    AndrewShmigs-MacBook-Pro:Documents new$ ls
    Habrahabr.sqlite
    AndrewShmigs-MacBook-Pro:Documents new$ sqlite3 Habrahabr.sqlite 
    SQLite version 3.7.12 2012-04-03 19:43:07
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> .schema
    CREATE TABLE ZBLOGPOST ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZAUTHOR INTEGER, ZCAPTION VARCHAR, ZTEXT VARCHAR );
    CREATE TABLE ZHAB ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZTARGET INTEGER, ZBLOGPOSTS INTEGER, ZNAME VARCHAR );
    CREATE TABLE ZORGANIZATION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZRATING INTEGER, ZNAME VARCHAR );
    CREATE TABLE ZQUESTION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZAUTHOR INTEGER, ZCAPTION VARCHAR, ZTEXT VARCHAR );
    CREATE TABLE ZRESPONSE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZQUESTION INTEGER, ZTEXT VARCHAR );
    CREATE TABLE ZTAG ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZBLOGPOST INTEGER, ZNAME VARCHAR );
    CREATE TABLE ZUSER ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZKARMA INTEGER, ZRATING INTEGER, ZORGANIZATION INTEGER, ZGENDER DECIMAL, ZAVATAR VARCHAR, ZEMAIL VARCHAR, ZNICKNAME VARCHAR );
    CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB);
    CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER);
    CREATE INDEX ZBLOGPOST_ZAUTHOR_INDEX ON ZBLOGPOST (ZAUTHOR);
    CREATE INDEX ZHAB_ZBLOGPOSTS_INDEX ON ZHAB (ZBLOGPOSTS);
    CREATE INDEX ZQUESTION_ZAUTHOR_INDEX ON ZQUESTION (ZAUTHOR);
    CREATE INDEX ZRESPONSE_ZQUESTION_INDEX ON ZRESPONSE (ZQUESTION);
    CREATE INDEX ZTAG_ZBLOGPOST_INDEX ON ZTAG (ZBLOGPOST);
    CREATE INDEX ZUSER_ZORGANIZATION_INDEX ON ZUSER (ZORGANIZATION);
    sqlite> select * from ZORGANIZATION;
    1|3|1|672|Yandex Inc.
    sqlite> select * from ZUSER;
    1|7|1|0|0|1|0||gosha.k@yandex.ru|Goshka
    2|7|1|0|0|1|1||vasilisa@yandex.ru|VaseaPup
    sqlite> 
    

    Добавим теперь одному из сотрудников вопрос и создадим какой-то пост.
    //    добавляем сотруднику Гоше вопрос
        NSManagedObject *whoAmI = [NSEntityDescription insertNewObjectForEntityForName:@"Question"
                                                                inManagedObjectContext:self.managedObjectContext];
        [whoAmI setValue:@"Who am I?" forKey:@"caption"];
        [whoAmI setValue:@"Помогите мне узнать себя лучше." forKey:@"text"];
        
        NSMutableSet *goshasQuestions = [gosha mutableSetValueForKey:@"questions"];
        [goshasQuestions addObject:whoAmI];
    

    Запустим приложение и проверим БД:
    sqlite> select * from ZQUESTION;
    1|4|1|4|Who am I?|Помогите мне узнать себя лучше.
    sqlite> 
    

    Добавим блогпост сотруднику Васе Пупкину:
    //    добавляем сотруднику Васе Пупкину новый блогпост
        NSManagedObject *newPost = [NSEntityDescription insertNewObjectForEntityForName:@"Blogpost"
                                                                 inManagedObjectContext:self.managedObjectContext];
        [newPost setValue:@"yandex.Деньги & yandex.Карты & yandex.ДваСтвола" forKey:@"caption"];
        [newPost setValue:@"Some text" forKey:@"text"];
        
    //    добавляем два Хаба
        NSManagedObject *hab1 = [NSEntityDescription insertNewObjectForEntityForName:@"Hab"
                                                              inManagedObjectContext:self.managedObjectContext];
        [hab1 setValue:@"iOS" forKey:@"name"];
        [hab1 setValue:@YES forKey:@"target"];
        
        NSManagedObject *hab2 = [NSEntityDescription insertNewObjectForEntityForName:@"Hab"
                                                              inManagedObjectContext:self.managedObjectContext];
        [hab2 setValue:@"Objective-C" forKey:@"name"];
        [hab2 setValue:@YES forKey:@"target"];
        
        NSMutableSet *habs = [newPost mutableSetValueForKey:@"habs"];
        [habs addObject:hab1];
        [habs addObject:hab2];
        
        [[pupkin mutableSetValueForKey:@"blogposts"] addObject:newPost];
    

    И вывод:
    sqlite> select * from ZBLOGPOST;
    1|1|1|5|yandex.Деньги & yandex.Карты & yandex.ДваСтвола|Some text
    sqlite> select * from ZHAB;
    1|2|1|1|1|iOS
    2|2|1|1|1|Objective-C
    sqlite> 
    


    Вывод данных

    Выведем всех сотрудников и наименования компаний в которых они работают. Код для чтения данных будем писать в том же методе в котором писали и запись данных.
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"User"];
        NSArray *allUsers = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
        
        for(NSManagedObject *user in allUsers){
            NSString *nickname = [user valueForKey:@"nickname"];
            NSString *organization = [user valueForKeyPath:@"organization.name"];
            
            NSLog(@"%@ works at %@", nickname, organization);
        }
    

    Получим примерно такой вывод (приложение у меня запускалось несколько раз и данные тоже несколько раз были добавлены):
    2013-08-31 13:00:27.255 Habrahabr[18148:c07] Goshka works at Yandex Inc.
    2013-08-31 13:00:27.257 Habrahabr[18148:c07] VaseaPup works at Yandex Inc.
    2013-08-31 13:00:27.258 Habrahabr[18148:c07] VaseaPup works at Yandex Inc.
    2013-08-31 13:00:27.258 Habrahabr[18148:c07] Goshka works at Yandex Inc.
    2013-08-31 13:00:27.259 Habrahabr[18148:c07] VaseaPup works at Yandex Inc.
    2013-08-31 13:00:27.259 Habrahabr[18148:c07] Goshka works at Yandex Inc.
    2013-08-31 13:00:27.260 Habrahabr[18148:c07] Finish!
    

    Обратите внимание на то, как мы получили наименование организации в которой работает пользователь. Как Вам? А? Я так и думал, что понравится!

    В завершение

    Экспериментируйте! Не бойтесь, если что-то сломается, полный проект находится по этой ссылке.

    Удачи и благодарю за внимание!
    Надеюсь вам понравилась практическая часть.

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 38

      +1
      Важность этой вашей серии постов трудно переоценить. Очередной раз большое спасибо!
        0
        Эххх, как приятно!
        Благодарю за отзыв!
        0
        Отличный материал =)
        Вы не планируете после публикации на хабре, опубликовать перевод на гитхаб?
        Удобно всё видеть в одном месте, а не кучей постов, пусть и с оглавлением.
          +3
          На Гитхабе — маловероятно, а вот вогнать всё в один пдф файл была идея.
            0
            Да, тоже хороший вариант завершения цикла. =)
              +1
              До завершения еще пилить и пилить, того глядишь в итоге отдельную книгу опубликуемс силами Хабрасообщества :)
                0
                А под какой лицензией распространяется оригинал? Что-то не смог найти эту информацию
                  0
                  Не могу ответить на ваш вопрос.
                  Ссылка с которой бралась книга здесь. Про лицензии нигде не смог найти.
                  А какие могут возникнуть проблем с переводом иностранной литературы? Он запрещен?
                    +1
                    Дело, которое Вы делаете полезно и Вам спасибо! Однако по вашему вопросу могу сказать следующее: юридические осложнения могут быть насколько я понял, так как Ваша работа использует материалы работы перевод, которой Вы делаете. В принципе дело можно трактовать и как производную работу от оригинальной, а такая работа уже требует разрешения от правообладателя оригинала. Хорошо, если я ошибаюсь, но озаботиться этим вопросом некоторый смысл есть, так как в самом худшем случае можно стокнутся с гражданским иском о нарушении авторских прав. Опять же, возможно, я не прав и хорошо, если так, к вышеописанным выводам я пришел разбираясь с вопросом о возможности распостранять перевод книги публично. Здесь просто еще есть такой эмпирический момент: все издательства, которые выпускают переводы делают это, имея разрешения издателей оригиналов как мне известно. Еще как мне известно ГК в части авторрских прав не считает освобождающим от ограничений АП факт некоммерческого использования. За работу и ее публикацию в любом случае спасибо и это было моим ИМХО
                      0
                      Этот вопрос всё чаще и чаще поднимается.
                      Что посоветуете делать? В какой момент перевод можно уже не считать переводом?

                      Не хотелось бы к концу перевода получить иск конечно же.
                        0
                        Я бы посоветовал только одно: проконсультироваться о ситуации хотя бы на каком-либо специализированном юридическом форуме ну и не бросать начатое дело:)
                          0
                          Еще один вариант: Вы же как я понимаю имеете определенный опыт разработки под ios и разбирались в теме, описанной в книге, так может написать набор руководств, охватывающих необходимый набор тем, или набор тем, родственных темам книги, полностью своими словами или используя гарантированно свободные материалы, но это конечно еще более хлопотное дело
                            0
                            Интересно, есть ли на Хабре юристы, которые смогу прояснить ситуацию…
                            Что касается второго ответа, то вопрос в следующем: можно ли уже текущий материал считать не переводом, а собственной подачей информации местами пересекающейся с исходной книгой?
                              0
                              Это и самому интересно, тут действительно нужны более подкованные хаброюзеры, единственное я у Вас там заметил иллюстрации, если сделаны самостоятельно, то минус одна проблема, если они из книги, то +1 проблема на пути к признанию работы самостоятельной
                                0
                                Неужели скриншот XCode является +1 проблемой?
                                Господи, избавь нас от копирастов!
            –6
            Зачем делать setValue forKey если есть типизированный объект User? Короче шлак…
            Лучше напишите о MagicalRecords и реализации Atomic Store, а не книжки из мана слепленые…
              0
              Благодарю за комментарий.
              Раз вам есть, что поведать народу — пишите статью! С удовольствием почитаем.
                –2
                Не за что. Наш диалог получился таким: — Напишите то-то. — Нет, напишите вы то-то. Смысла ноль. А народ я смотрю, не очень любит суть — лучше размазать по стенам. Ну что же. Какой тогда смысл в этом всём?
                  0
                  Обычно происходит так: если вам что-то не нравится, то вы делаете по своему и потом происходит оценка со стороны.
                  Вы, я как вижу, кроме пустой болтовни много не можете. Не так ли?
                    –1
                    Как обычно и где происходит, это вообще не стоит обсуждения. Вы меня сами вынуждаете писать дальше. А болтовни никакой не было. Я задал конкретный вопрос, на который Вы не ответили. Сказал, что книжка — то же самое, что написано в мануале, а то может еще и хуже. Это не пустая болтовня. И предложеил Вам (заметте я не говорил, что я крутой мега чувак) написать о действительно интересных вещах. Так что у меня всё нормально с болтовнёй.
                      +1
                      1) Понятие «интересный» каждый волен трактовать по-своему.
                      2) Вы не ограничились высказыванием, что материалы присутствуют и в документации, а добавили грубую фразу («Короче шлак…»)
                      3) Если книга хуже, чем мануал, то вместо критикующих комментариев указали бы в каком месте она хуже и каким образом можно улучшить материал.
                      4) Где вы там увидели типизированный объект User? Пример покажите без setValue:forKey:. Ждемс, причем в контексте данного примера.
                      5) Раз вы не мега крутой чувак, то изменили бы тон с которым предлагаете писать на указанные вами темы, причем есть доля вероятности, что приведенные выше темы вы использовали для того, чтобы «испугать» тех, кто никогда ранее об этом не слышал.

                      Отступление: перед тем, как начать ездить на болиде надо научиться ездить на картах, а если вы предлагаете сразу посадить вас в болид (что равносильно вручить вам пистолет и предложить застрелиться), то дело ваше.
                        –2
                        Я еще раз говорю, что это шлак, потому что ORM это ORM, а не Base Class RM, и если Вы не поймёте, что я написал, то мне нечего распинаться и отвечать на Ваши расписаные мантры которые Вы высасываете из пальца. Вообщем мой вердикт уже описан выше.
                          0
                          Ну вместо того, чтобы писать очередные «мне лень распинаться» ответили бы на мои вопросы и закрыли бы тему.
                          Не скрываю, что чего-то могу не знать, но хочу узнать. Просвятите.
                            –2
                            Зачем мне отвечать на Ваши перекрученые, если Вы не ответили на мой нормальный? Вообщем, Вы не то, что что то не знаете, Вы элементарного не знаете. Вопрос у меня вполне конкретный и понятный, а то, что Вы его не поняли показывает Ваше незнание слишком явно.
                            0
                            С каих это пор CoreData — ORM?
                              –3
                              А Вы можете это доказать, только не абстрактными предложениями типа «Core Data не маппит чё то там» (потому что она кое что маппит, и это не прокатит)?
                                0
                                Object graph management и точка.

                                А persistence в SQLite это так, приятная плюшка.
                                  –3
                                  Кстати «и точка» — это сильно! Ты реальный чувак! Молодец. Всех сделал. Только вот прикол в том, что я прав с самого начала этой уже бессмысленной траты времени на вас четверых и доказать обратное вы не можете. Только нелепые высказывания не по сути. Мой первый комментарий уминает все ваши дальнейшие «по умолчанию». Не хочу тратить свою жизнь, доказывая то, что и так понятно.
                                    +2
                                    Ну уж извините, но то что написал я, написано и на первой странице документации Core Data.
                                      –3
                                      Ну молодец! Я тоже могу написать то, что написано в книге и в документации. Это не составляет труда. А вот реально что то сделать вы не можете. Я недеюсь понятно, что слова Object graph management ничего не доказывают? Или и это нужно объяснять?
                                        +1
                                        Ну то есть Вы (когда это мы перешли на «ты»?) считаете что знаете фреймворк лучше его создателей? Рад за Вас.
                                          –2
                                          Аааа, то есть если там не написано ORM, значит это всё доказывает да? Если так, то тогда это конечно всё доказывает. Просто супер. Не надо меня разводить на всякую чушь либо пишите конкретику по теме либо я не буду отвечать дальше на эту ВАШУ ерунду!
                                            +2
                                            Надеюсь ты и правда больше не будешь отвечать. Для всех адекватных людей:

                                            CoreData нельзя назвать ORM по нескольким причинам — во-первых, в качестве хранилища может быть использована не только SQLite, но и нереляционные хранилища (ссылка); во-вторых (на самом деле следствие первого) нельзя использовать базу SQLite и напрямую, и через CoreData (или привязать CoreData к готовой базе (ссылка)). То есть замапить что-то куда-то действительно нельзя.
                                              0
                                              Вы мыслите слишком узко, что бы что то доказать. Какие то нелепые вещи пишите. «Не только SQLite может быть использована, но он может быть использована» какая разница что там еще, факт в том, что реляционное хранилище может быть использовано. Вот тут и всё проявляется. И мапится всё как раз с момощью модели, только вот это делает программист. А сут таже. Прост Вы не понимаете сути, того что по схеме, геренируется модель, совокупность объектов которой представляет собой отражение объектов на реляционну структуру.
                              +1
                              Ваша критика неконструктивна, а грубые высказывания только говорят о вашем непрофессионализме. И плевать, знаете вы что-то больше автора или нет, вы показали себя с худшей стороны. Критикуя таким образом, вы вызываете негатив к себе и никаким образом это не улучшит качество материала.
                                –2
                                Всё конструктивно. В моём первом комментаии всё очень понятно и всё к месту. Если правда глаза режет — то это не мои проблемы. А Вы дальше читайте эти «важные» статьи. Любой дурак может взять и написать то, что написано в книге другими людьми. Только вот книги разные бывают и люди по разному понимаю где качество, а где шлак. Удачи!
                  –2
                  Как можно вот так вот взять и из всей книги выдрать самый базовый пример даже без создания моделей, не говоря уж об использовании transient аттрибутов?) Что ж, теперь, видимо, покупать придется…
                    0
                    Не из всей книги, а из второй главы. Разница есть.

                  Only users with full accounts can post comments. Log in, please.