2015-03-20 3 views
1

ОК, у меня есть таблица с тремя различными ячейками прототипа (cellVaccination, cellAdmin, cellExpire). В моем методе cellForRowAtIndexPath я раскалывается объект ядра данных через эти 3 отдельных клеток, так что структурно таблица будет выглядеть следующим образом:dequeueReusableCellWithIdentifier и пользовательские ячейки

- Drug 1 
    - Drug 1 Admin 
    - Drug 1 Expire 
- Drug 2 
    - Drug 2 Admin 
    - Drug 2 Expire 
- Drug 3 
    - Drug 3 Admin 
    - Drug 3 Expire 

Дополнительно, я программно добавил UISwitch в «верхней (т.е. препарат 1), так что коммутатор может управлять дополнительными функциями ячеек (например, цветом, текстом и т. д.). Вот что мой нынешний cellForRowAtIndexPath выглядит следующим образом:

- (VaccineTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    // we need to adjust the indexPath because we split a single core data object into 3 different rows 
    NSIndexPath *adjustedIndexPath = [NSIndexPath indexPathForRow:indexPath.row/3 inSection:indexPath.section]; 
    Vaccine *vaccine = [self.fetchedResultsController objectAtIndexPath:adjustedIndexPath]; 

    // define the switch that will get added to the primary table rows 
    UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero]; 

    if (indexPath.row % 3 == 0) { 
     static NSString *cellIdentifier = @"cellVaccination"; 
     VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; 
     cell.vaccineName.text = vaccine.vaccineName; 

     // add a switch into that table row 
     cell.accessoryView = switchview; 
     [switchview addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; 
     switchview.tag = indexPath.row; 
     switchview.on = [vaccine.vaccineEnabled boolValue]; 

     // PROBLEM AREA BELOW 
     if (switchview.on) { 
      VaccineTableViewCell *cell1 = [myTableView dequeueReusableCellWithIdentifier:@"cellAdmin" forIndexPath:[NSIndexPath indexPathForItem:indexPath.row + 1 inSection:0]]; 
      cell1.vaccineAdmin.textColor = [UIColor redColor]; 
      cell1.vaccineAdminDate.textColor = [UIColor redColor]; 

      NSLog(@"Row %d is %@", indexPath.row, switchview.on ? @"ON" : @"OFF"); 
     } else { 
      VaccineTableViewCell *cell1 = [myTableView dequeueReusableCellWithIdentifier:@"cellAdmin" forIndexPath:[NSIndexPath indexPathForItem:indexPath.row + 1 inSection:0]]; 
      cell1.vaccineAdmin.textColor = [UIColor lightGrayColor]; 
      cell1.vaccineAdminDate.textColor = [UIColor lightGrayColor]; 

      NSLog(@"Row %d is %@", indexPath.row, switchview.on ? @"ON" : @"OFF"); 
     }  
     // 

     return cell; 
    } 

    else if (indexPath.row % 3 == 1) { 
     VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:@"cellAdmin" forIndexPath:indexPath]; 
     cell.vaccineAdminDate.text = vaccine.vaccineAdmin; 
     return cell; 
    } 

    else if (indexPath.row % 3 == 2) { 
     VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:@"cellExpire" forIndexPath:indexPath]; 
     cell.vaccineExpireDate.text = vaccine.vaccineExpire; 
     return cell; 
    } 

    else { 
     // do nothing at the moment 
    } 
} 

Проблема у меня, кажется, происходит вокруг области, записанной в «проблемной области ниже» элемент, более конкретно я угадываю с dequeueReusableCellWithIdentifier. Теоретически, что должно произойти, так это то, что, когда ячейки сначала заполняются объектами Core Data, я хочу проверить, включен ли переключатель «on» или «off», и соответствующим образом отрегулировать параметр (например, цвет) что без какого-либо другого взаимодействия соответствующие строки окрашены соответствующим образом.

Что происходит, предположим, что я имитирую на iPhone 4S и что на экране отображаются 4 ряда строк или всего 12 строк (4 строки из 3 разных прототипов). Предположим также, что первые 2 включены, а второй 2 выключены, снова управляются непосредственно из Core Data. Первоначально экран будет выглядеть правильно, первые два элемента окрашены в красный цвет, а следующие два элемента окрашены в серый цвет. Однако, когда я начинаю прокручивать свой стол вверх, NEXT два (которые были на экране) окрашены в красный цвет, и поэтому шаблон продолжается. Как ни странно, когда NSLog возвращает идентификаторы строк (видели в этом разделе «проблемная область») все выглядит, как это правильно идентифицировать необходимые строки, но, видимо, это не так, то есть:

vaccinations[10952:1486529] Row 0 is ON 
vaccinations[10952:1486529] Row 3 is ON 
vaccinations[10952:1486529] Row 6 is OFF 
vaccinations[10952:1486529] Row 9 is OFF 
vaccinations[10952:1486529] Row 12 is OFF 
vaccinations[10952:1486529] Row 15 is OFF 

Я считаю, что это что-то делать с dequeueReusableCellWithIdentifier, однако почему NSLog правильно идентифицирует строки, но изменение цветов не попадает в правильные строки?

+0

Это может иметь какое-то отношение к вашему программному добавлению uiswitch. Любая причина, по которой вы не просто добавляете это в свои ячейки в раскадровке? – Alex

+0

Мне нужно иметь возможность ссылаться на переключатели по номеру тега позже, и это самый простой способ создания уникальных тегов - по мере создания ячеек. Кроме того, имейте в виду, что indexPath.row возвращает правильные ячейки и их правильные состояния переключателя, однако, когда я пытаюсь использовать indexPath.row в процедуре dequeueReusableCellWithIdentifier, я не могу постоянно нацеливаться на одни и те же ячейки. – pscarnegie

+0

где вы добавляете переключатель в свою ячейку? – Alex

ответ

1

У вас есть ссылки на cell1, в котором вы деактивируете ячейку для другого NSIndexPath, настройте цвет этой ячейки и отбросите эту ячейку. Я предполагаю, что вы пытаетесь настроить внешний вид другой ячейки (следующей ячейки).

Неправильное. cellForRowAtIndexPath должен регулировать только состояние текущей ячейки. Если вы хотите настроить внешний вид ячейки cellAdmin, вы должны сделать это в блоке if (indexPath.row % 3 == 1) ....

Таким образом, блок if (indexPath.row % 3 == 0) будет искать в модели, чтобы определить, включен или выключен переключатель. Блок if (indexPath.row % 3 == 1) будет искать в модели, чтобы определить, какой цвет должен быть.

Но cellForRowAtIndexPath не должен пытаться настроить внешний вид другой ячейки. У вас нет гарантий того, какой порядок будет создан (и это может зависеть от того, будет ли ваша прокрутка, с какого направления и т. Д.).

Если кто-то захотел обновить другую видимую ячейку, то dequeueReusableCellWithIdentifier - неправильный метод, независимо. Вместо этого следует использовать [tableView cellForRowAtIndexPath:], который извлекает ячейку для видимой в данный момент ячейки (и ее не следует путать с аналогичным способом UITableViewDataSource). Но вы никогда не сделаете этого в этом контексте, потому что не знаете, была ли эта другая ячейка загружена или нет.(Я на самом деле считаю, что плохая практика вообще обновлять другую ячейку в любом контексте, что является нарушением разделения обязанностей.)

+0

Роб, благодарю вас за ваши идеи. Они были очень хорошо объяснены. Первоначально мое намерение состояло в том, чтобы показывать только «дочерние» ячейки при включении коммутатора, но это оказалось еще более сложной дилеммой в одной таблице разделов. В конце концов я планирую встроить встроенные подборщики дат, чтобы можно было выбрать дату для обеих дочерних ячеек. Поскольку скрытие их казалось более сложным, мой план состоял в том, чтобы просто «отключить» взаимодействие с пользователем и серых ячеек, когда переключатель был выключен, а не скрывал их. Какие-либо предложения в отношении этих усилий? Кажется, достаточно просто теоретически, но, по-видимому, не на практике. – pscarnegie

+0

Если вы ищете «uifyview collapse», вы, вероятно, найдете всевозможные ссылки, например http://stackoverflow.com/questions/1938921/expand-collapse-section-in-uitableview. Но принцип по-прежнему сохраняется: вы не обновляете/не показываете/не скрываете другие ячейки, а скорее, когда вы переворачиваете коммутатор, вы соответствующим образом обновляете свою модель, а затем вызываете соответствующий метод для перезагрузки соответствующих ячеек. Принцип управления заключается в том, чтобы отделить представление/щелчок переключателя в одной ячейке от обновления других ячеек. – Rob

+0

Мой основной объект данных состоит из отдельной записи, содержащей имя, дату администратора, дату истечения срока действия и состояние переключения, которая разбивается на отдельные ячейки с этими операторами модуля. Удаление администратора и срок действия, чтобы удалить эти ячейки (с обновлением таблицы), казалось бы, потребовало бы другой модели данных ядра, да? Или это можно сделать с его текущей структурой? – pscarnegie