2013-11-19 1 views
0

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

Давайте сделаем шаг назад, чтобы посмотреть на Модель, и предпосылка приложения проста; позволяют пользователям создавать «Транзакции», которые имеют имя, сумму, случай и дату - при создании новой транзакции пользователю должно быть разрешено выбирать существующее имя. Модель данных:

  • Сделка Entity с wasGiven атрибут
  • Person Entity с атрибутом имени
  • Случай Entity с названием атрибута
  • Item Entity с количеством атрибутов

сделка имеет отношения к объекту Person (whoBy), ссылку на сущность события (случай) и ссылку на Entity Item (itemType).

Приложение представляет собой простой 2 Tableb-ed Table View Controller - первая вкладка содержит всю информацию, разделенную датами. Вторая вкладка содержит только информацию «Имя». Существует кнопка «плюс», и когда пользователь нажимает на нее, ей предоставляется модальный вид, чтобы добавить имя, случай, количество и дату. Они нажимают кнопку сохранения и сохраняют ее в базе данных основных данных.

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

Код

Я прошел через несколько итераций, чтобы попытаться получить эту работу, и вот последний код, используя подклассы NSManagedObject.

Управляемый объектObjectContext получен из приложения-делегата.

Название, событие, количество и дата хранятся в их собственных текстовых полях.

AddEntry.m - Сохранить метод

- (IBAction)save:(id)sender 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context]; 
    Item *itemType = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:context]; 
    Person *p = (Person *)[Person personWithName:self.nameTextField.text inManagedObjectContext:context]; 
    Occasion *o = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text andEventDate:self.dateTextField.text inManagedObjectContext:context]; 

    transaction.whoBy = p; 
    occasion.title = self.occasionTextField.text; 
    transaction.occasion = o; 


    itemType.amount = self.itemTextField.text; 
    transaction.item = itemType; 
    transaction.wasReceived = @(self.isReceivedSegment.selectedSegmentIndex == 0); 
    NSError *error = nil; 
    if (![context save:&error]) 
    { 
     NSLog(@"Can't save! %@ %@", error, [error localizedDescription]); 
    } 
    [self dismissViewControllerAnimated:YES completion:nil]; 
} 

Это, конечно, вызывает подкласс Person NSManagedObject и здесь, где я прошел через несколько итераций.

Person NSManagedObject Подкласс - Итерация 1 - Предикаты

+ (Occasion *)eventWithName:(NSString *)title andEventDate:(NSString *)date inManagedObjectContext:(NSManagedObjectContext *)context; 
{ 
    Occasion *occasion = nil; 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"]; 
    request.predicate = [NSPredicate predicateWithFormat:@"title = %@", title]; 
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]; 
    request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 

    NSError *error = nil; 
    NSArray *occasions = [context executeFetchRequest:request error:&error]; 

    if (!occasions) 
    { 
     // Handle Error 
    } 
    else if (![occasions count]) 
    { 
     occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context]; 
     occasion.title = title; 
    } 
    else 
    { 
     occasion = [occasions lastObject]; 
    } 
    occasion.dateOfEvent = date; 
    return occasion; 
} 

Проблема Это несколько работ.Я поставил точку останова, и возвращаемый «человек», который возвращается сюда, и метод сохранения в Add Entry тот же, если объект уже существует и новый, если это новый объект, но когда дело доходит до второй вкладки, добавив вторую запись для того же человека.

Итерация 2 - ObjectId

С пытается получить идентификатор объекта, я получаю тот же результат дублированных записей во второй вкладке:

+ (Person *)personWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context; 
{ 
    Person *person; 

    NSManagedObjectID *personID = person.objectID; 

    if (!personID) 
    { 
     person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context]; 
     person.name = name; 
     return person; 
    } 
    else 
    { 
     return person; 
    } 
} 

В случае имеет значение, то Вторая вкладка в fetchRequest выглядит следующим образом:

- (NSFetchedResultsController *)fetchedResultsController 
{ 
    if (_fetchedResultsController != nil) 
    { 
     return _fetchedResultsController; 
    } 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Occasion" inManagedObjectContext:managedObjectContext]; 
    fetchRequest.entity = entity; 
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO]; 
    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort]; 
    fetchRequest.fetchBatchSize = 20; 
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 
    self.fetchedResultsController = theFetchedResultsController; 
    _fetchedResultsController.delegate = self; 
    return _fetchedResultsController; 
} 

EDIT Мне интересно, есть ли тот факт, что у меня нет предиката здесь, во второй вкладке fetchRequest означает, что он иллюстрирует ВСЕ объекты.

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

Это сводит меня с ума и действительно останавливает мое приложение от прогрессирования, поэтому любая помощь здесь была бы оценена по достоинству!

EDIT: Модель данных в комплекте

enter image description here

+0

Вы отлаживали «он все еще добавляет вторую запись для одного и того же человека» - это одно и то же MO в листинге дважды? Или у вас 2 с тем же именем? – Wain

+0

Привет @ Хороший вопрос - я должен проверить, что - тот же самый возвращаемый человек присутствовал при использовании существующего имени, но это не значит, что МО было одинаковым - какой был бы лучший способ отладить это? – amitsbajaj

+0

Если я правильно понимаю, что «whoBy» - это отношение. Как это определяется? – AntonijoDev

ответ

1

Хорошо это это то, что происходит ... U добавить первую транзакцию и имя U предоставить Джеку, затем U добавить вторую транзакцию (далее текст) и добавить имя John, после U добавить третий T с именем Jack и добавить другое с именем John. Если U взглянуть на таблицы в базе данных, вы увидите, что таблица Transitions имеет 4 записи, потому что вы добавили 4 перехода, но у людей только два. У этого есть 2, потому что вы добавили фильтр для ввода Персоналии, чтобы он не мог содержать два одинаковых имени. И ошибка, которую вы сделали, заключается в том, что U попытался извлечь из таблицы перехода все записи. Конечно, U получает 4 имени (2 Джона и 2 Джека), поэтому R 4 записи в таблице Transition и каждый связан с записью Person. Если U хочет получить всех людей, вы не должны получать их из таблицы перехода, вы должны сделать это из таблицы лиц или добавить [r setReturnsDistinctResults: YES]; на ваш запрос выборки в случае, когда U R извлекает из таблицы Transition ... Я думаю, что есть способ установить различное свойство, но я не знаю синтаксиса. Таким образом, проблема в том, что вы хотите сделать, хотите ли вы представить всех людей, которых у вас есть в своей базе данных, или вы хотите представить имена на своих переходах, что означает, что одни и те же люди могли делать разные переходы. См. ...

+0

Бад, спасибо огромное - это потрясающе - я чувствую, что мы на правильном пути. В представлении «Персоны» я хочу отобразить список имен «UNIQUE» .. так что, если у меня есть две записи для Джона и две для Джека, я хочу видеть только Джека и Джона (один раз каждый) .. тогда, когда я нажимаю на Джона, я иду в ДРУГОЙ вид стола, чтобы увидеть все транзакции Джона, и я могу вернуться к этому представлению в таблице, а затем щелкнуть по Джеку и посмотреть все его ... это имеет смысл? Если это так, в представлении «Таблица лиц» я бы искал личность или транзакцию? Применить предикат? Каким должен быть код. – amitsbajaj

+0

Управляемый выбор должен быть таким же, как и не извлекать из объекта T, извлекать из сущности лиц и в дескрипторе sort потерять «whoBy». потому что это не существует в Лицах, пишите только «имя», и вот оно – AntonijoDev

+0

Это работает как абсолютное удовольствие! Большое спасибо моему другу !! :) У меня есть еще один вопрос, хотя (еще одна проблема), но я не уверен, что здесь подходящее место, чтобы спросить его. На вкладке человека, когда я выбираю человека (который теперь показывает ОДИН элемент!), Еще раз спасибо), он создает исключение, и я подозреваю, что причина в том, что в представлении NEW Table, который действует как представление таблицы, когда строка выбрана в представлении Person, я передаю объект транзакции вместо Person - однако .. I нужна транзакция, потому что мне нужно отобразить другую информацию из ссылок транзакции ... shud Я прошу новый q? – amitsbajaj

0

Я persum, что у вас есть сделка < < так многих лиц в сделке управляемого объекта у вас есть набор людей из-за отношения. Когда вы добавляете того же человека в транзакцию, он создает новый управляемый объект и добавляет его в набор, и если вы выберете по имени, у вас будет несколько записей транзакции с таким же именем, но это не означает, что у вас есть несколько Лица. Есть выборки на столе лиц, непосредственно, и вы увидите, что значения различны ...

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

+0

Спасибо, бутон - это очень интересно. Это правильно в отношениях, и одна вещь, которую я новичок, насколько я могу видеть (новичок в разработке iOS), я не добавляю никого в какой-либо набор - какой код вам нужно будет, чтобы подтвердить это? Кроме того, должен ли я помещать предикат в Fetch? Если да, то что это должно быть? – amitsbajaj

+0

Да U R -> transaction.whoBy = p; – AntonijoDev

+0

Только он делает это для U – AntonijoDev

Смежные вопросы