Ячейки UITableView, содержащие несоответствующее обновление UISwitch - PullRequest
0 голосов
/ 13 ноября 2018

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

Однако, тогда у меня появилась блестящая идея также выполнить переключение, когда выбрана вся строка таблицы. Простое в теории верно? И это было с точки зрения обновления модели данных.

Однако, по любой причине, из-за которой я был в тупике в течение последних 2 часов, только переключатель в ячейке № 3 обновляется, чтобы отразить изменение состояния при перезагрузке данных таблицы. Независимо от того, сколько строк у меня в таблице, всегда работает только третья ячейка. Если ячеек меньше 3, то ни одна из них не работает.

Я поместил туда нагрузку NSLog вызовов, и они отражают правильные состояния данных, как я всегда ожидал, но они просто не отражаются в коммутаторе после первой загрузки. Если я оставляю контроллер вида, а затем возвращаюсь, все переключатели установлены правильно ...

Я просто знаю, что это будет какая-то глупость, которую я где-то совершил, потому что это работает ровно в одном случае, но для моей жизни я не вижу этого: (

Можете ли вы?

-(void)viewDidLoad
{
    [super viewDidLoad];

    [_tableAddPeople setDelegate:self];
    [_tableAddPeople setDataSource:self];
}

-(void)viewWillAppear:(BOOL)animated
{
    [_tableAddPeople reloadData];
}

-(void)listSwitchChanged:(id)sender
{
    UISwitch * switchControl = sender;

    Person * person = [SAVE_DATA getPersonWithIndex:(int)switchControl.tag];

    if (switchControl.on)
    {
        [SAVE_DATA activePeopleAdd:person.tag];
    }
    else
    {
        [SAVE_DATA activePeopleRemove:person.tag];
    }
}


#pragma mark UITableViewDataSource Delegate

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [SAVE_DATA peopleCount];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell * cell = [_tableAddPeople dequeueReusableCellWithIdentifier:@"AddPeopleCell"];

    UILabel * nameLabel = (UILabel *)[cell.contentView viewWithTag:1];
    UISwitch * activeSwitch = (UISwitch *)[cell.contentView viewWithTag:2];

    Person * person = [SAVE_DATA getPersonWithIndex:(int)[indexPath row]];

    [nameLabel setText:[person name]];

    BOOL active = [SAVE_DATA activePeopleContains:person.tag];
    NSLog(@"Row for %@ is %@", person.name, (active? @"ON" : @"OFF"));
    [activeSwitch setOn:active animated:YES];
    [activeSwitch addTarget:self action:@selector(listSwitchChanged:) forControlEvents:UIControlEventValueChanged];
    activeSwitch.tag = (int)[indexPath row];

    return cell;
}

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}

-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}


#pragma mark UITableView Delegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    Person * person = [SAVE_DATA getPersonWithIndex:(int)[indexPath row]];

    if ([SAVE_DATA activePeopleContains:person.tag])
    {
        NSLog(@"Removing %@", person.name);
        [SAVE_DATA activePeopleRemove:person.tag];
    }
    else
    {
        NSLog(@"Adding %@", person.name);
        [SAVE_DATA activePeopleAdd:person.tag];
    }

    [_tableAddPeople reloadData];
    //dispatch_async(dispatch_get_main_queue(), ^{[tableView reloadData];});
}

1 Ответ

0 голосов
/ 13 ноября 2018

Ваша проблема в том, что вы используете свойство switch tag для двух вещей:

  1. Чтобы идентифицировать его в иерархии представления (Вам присвоено значение '2')
  2. Чтобы определить, в каком ряду переключатель был изменен

Поскольку вы присваиваете indexPath.row для tag, в случае, когда путь индекса не равен 2 (т. Е. В третьей строке), [cell.contentView viewWithTag:2]; вернет nil, когда ячейка будет использоваться повторно.

У вас также есть проблема с повторным использованием ячейки, поскольку вы добавляете обработчик действия переключения несколько раз.

Я бы предложил вам принять следующий подход:

  1. Предоставьте вложенные представления вашей ячейки, используя свойства, и приведите результат dequeueReusableCell к вашему подклассу UITableViewCell, чтобы вы могли получить к ним доступ без необходимости использовать тег

  2. Установите ваш подкласс UITableViewCell в качестве обработчика действия переключателя.

  3. Реализуйте шаблон делегирования между ячейкой и вашим контроллером представления, чтобы ячейка могла уведомить контроллер представления о том, что коммутатор изменился. Ячейка может передать self методу делегата. В методе делегата вы можете использовать indexPathForCell для определения затронутой строки.

  4. Не перезагружайте весь просмотр таблицы только потому, что изменилась одна строка. Перезагрузите только поврежденный ряд.

...