2010-11-03 3 views
0

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

Если я не объясняю ясно, вот пример. Я хочу изменить имя этого списка, поэтому я нажимаю «Редактировать», нажимаю на список, нажимаю строку «Список имен», всплывает клавиатура, набираю новое имя, нажимаю «Готово», и он возвращает меня обратно в RVC без изменений сохранены. Я несколько минут стучал головой об этом и хотел бы помочь!

Вот соответствующий код из ListDetailViewController:

- (void)viewDidLoad { 
[super viewDidLoad]; 
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] 
           initWithBarButtonSystemItem:UIBarButtonSystemItemDone 
           target:self 
           action:@selector(done)]; 
self.navigationItem.rightBarButtonItem = doneButton; 
[doneButton release]; 

self.tableView.allowsSelection = NO; 
self.tableView.allowsSelectionDuringEditing = NO; 
} 



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
// Return the number of rows in the section. 
return 3; 
} 


// Customize the appearance of table view cells. 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
static NSString *DetailCellIdentifier = @"DetailCell"; 

ListDetailCell *cell = (ListDetailCell *)[tableView dequeueReusableCellWithIdentifier:DetailCellIdentifier]; 
if (cell == nil) { 
    [[NSBundle mainBundle] loadNibNamed:@"ListDetailCell" owner:self options:nil]; 
    cell = listDetailCell; 
    self.listDetailCell = nil; 

// Configure the cell... 

    // list name 
    if (0 == indexPath.row) { 
     cell.label.text = @"List Name"; 
     cell.textField.text = self.selectedList.listName; 
     cell.textField.placeholder = @"Name"; 
    } 

    // Detail 1 
    if (1 == indexPath.row) { 
     cell.label.text = @"Detail 1"; 
     cell.textField.text = selectedList.detail1; 
     cell.textField.placeholder = @"Detail 1"; 
    } 

    // Detail 2 
    if (2 == indexPath.row) { 
     cell.label.text = @"Detail 2"; 
     cell.textField.text = selectedList.detail2; 
     cell.textField.placeholder = @"Detail 2"; 
    } 
} 

return cell; 
} 


- (void)done { 
[self.listDetailCell resignFirstResponder]; 
[self.navigationController popViewControllerAnimated:YES]; 
} 

В Ивар label и textField объявлены в ListDetailCell, что ячейка таблицы СИБ я упоминал ранее.

ответ

3

Не уверен, что у меня есть проблема, или мой ответ - лучший метод, но это то, что я сделал недавно. У меня есть TableViewController и UITableView, которые отображают ряд пользовательских ячеек для редактирования данных. Это в основном реплицирует то, что я видел, как это делают другие приложения для создания экранов редактирования данных.

Каждая из пользовательских ячеек имеет UITextField. Когда пользователь заканчивает редактирование ячейки, UITextField запускает сообщение в UITextFieldDelegate. Поэтому я добавил протокол UITextFieldDelegate в TableViewController и при настройке настраиваемой ячейки в cellForRowAtIndexPath я установил TableViewController как делегат UITextFields. Затем, когда пользователь заканчивает редактирование, отправляется сообщение редактирования конца, и я могу получить значение из UITextField и сохранить его обратно в управляемом объекте объекта.

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

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

  • В коде для сообщения делегата вам необходимо сначала определить UITextField, который инициировал вызов. Лучший способ сделать это - установить свойство Tag на UITextField, когда вы создаете UITableCell, который его содержит. Затем в методе делегата вы можете использовать оператор switch для выбора поля объекта для сохранения значения.

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

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

  • Если у вас есть UITextView, они используют другой делегат.

Для добавления делегата вам нужно будет сделать что-то вроде этого (взятый из кода выше):

@interface MyTableViewController : UITableViewController <UITextFieldDelegate> 

.... 

    if (0 == indexPath.row) { 
     cell.label.text = @"List Name"; 
     cell.textField.text = self.selectedList.listName; 
     cell.textField.placeholder = @"Name"; 

     cell.textField.delegate = self; // Setting controller as text field delegate. 
     cell.textField.tag = 1; // Really should use an enum here for clarity. 

    } 

.... 

-(void) textFieldDidEndEditing:(UITextField *) textField { 
    switch(textField.tag) { 
     case 1: //Again with the enum. 
      // Save field 1. 
      entity.someProperty = textField.text; 
     .... 
    } 
} 

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

+0

Следует ли добавить делегат в класс ячеек или метод cellForRowAtIndexPath? И клавиатура не проблема, так как кнопка «Готово» и контроллер контроллера работают так, как они предполагают. Я изменил свой пример для ясности, чтобы быть более ясным! –

+0

Я обновил выше, чтобы добавить пример кода. Остерегайтесь опечаток, я вручную набрал его в :-) – drekka

+0

Это сделало это, спасибо! Я все еще обволакиваю своих делегатов, и каждый новый бит помогает. :) –