UISwitch внутри UITableViewCell


У меня есть табличное представление с пользовательской ячейкой (UISwitch на каждой ячейке tableview).

Я установил свою ячейку так:

switchView = [[UISwitch alloc] initWithFrame:CGRectMake(200.0f, 5.0f, 75.0f, 30.0f)];
cell.accessoryView = switchView;
[switchView setOn:NO animated:NO];
[switchView addTarget:self action:@selector(favorite:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:switchView];

И действие, которое вызывается пользователем, когда он изменяет UISwitch:

-(IBAction)favorite:(id)sender 
{
    indexPath = [self.tableView indexPathForCell:(UITableViewCell*)[sender superview]];
    NSMutableArray *favoriteList = [[NSMutableArray alloc]init];
    NSString *favoriteItem = [self.tableView cellForRowAtIndexPath:indexPath].textLabel.text;
    NSLog(favoriteItem);

    if ([switchView isOn]) 
    {
        [favoriteList addObject:favoriteItem];

        NSUserDefaults *favoriteDefaults = [NSUserDefaults standardUserDefaults];
        [favoriteDefaults setObject:favoriteList forKey:@"MyFavorites"];
        NSLog(@"%@", favoriteList);
    }
    else
    {
        [favoriteList removeObject:favoriteItem];

        NSUserDefaults *favoriteDefaults = [NSUserDefaults standardUserDefaults];
        [favoriteDefaults setObject:favoriteList forKey:@"MyFavorites"];
        NSLog(@"%@", favoriteList);
    }
}

Проблема в следующем:
При тестировании приложения правильно работает только последний элемент (ячейка) табличного представления.

Для остальных отладчик возвращает, что состояние UISwitch всегда "выключено".

В чем проблема?

1 2

1 ответ:

Пара мгновенных реакций:

  1. В (IBAction)favorite:(id)sender вы не захватываете switchView для рассматриваемой ячейки, а просто используете то, что использовалось последней ссылкой этого класса ivar. Аналогично, в вашем cellForRowAtIndexPath, вы, по-видимому, устанавливаете (и многократно сбрасываете) этот самый, единственный switchView Ивар. Наверное, Ивара вообще не должно быть. Вы можете сделать switchView локальной переменной cellForRowAtIndexPath. Вы также можете сделать его локальной переменной favorite. Но самое главное, favorite должен устанавливаем его как UISwitch *switchView = sender.

  2. Я предполагаю, что вы хотите сохранить все ваши избранные значения по умолчанию. Ваш текущий (IBAction)favorite:(id)sender будет воссоздавать favoriteList каждый раз, и он будет иметь либо один элемент в нем, либо никаких элементов в нем, но, конечно, отбрасывая любые другие избранные, которые вы могли выбрать в прошлом.

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

Итак, я бы предложил изменить cellForRowAtIndexPath следующим образом:

NSString *title = [_favorites objectAtIndex:indexPath.row]; // clearly, you'll get the text however you're getting your text now ... I'm just storing in array
cell.textLabel.text = title;

BOOL isFav = [self isFavorite:title]; // go to user defaults and find out if it's there or not

UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectMake(200.0f, 5.0f, 75.0f, 30.0f)];
[switchView setOn:isFav animated:NO];
[switchView addTarget:self action:@selector(toggleFavoriteSwitch:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = switchView;

Здесь используется isFavorite:

- (BOOL)isFavorite:(NSString *)title
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSArray *listOfFavorites = [userDefaults objectForKey:kMyFavsKey];

    if (listOfFavorites)
        return [listOfFavorites containsObject:title];

    return NO;
}

Тогда, очевидно, вам нужно определить свой toggleFavoriteSwitch (ранее называемый favorite) метод:

- (IBAction)toggleFavoriteSwitch:(UISwitch *)switchView
{
    UITableViewCell *cell = (UITableViewCell *)[switchView superview];

    [self updateFavoriteInUserDefaultsFor:cell.textLabel.text withValue:[switchView isOn]];
}

И это обновление пользовательских настроек по умолчанию следующим образом:

- (void)updateFavoriteInUserDefaultsFor:(NSString *)title withValue:(BOOL)isOn
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    NSArray *oldFavorites = [userDefaults objectForKey:kMyFavsKey];

    NSMutableArray *newFavorites;

    if (!oldFavorites)
        newFavorites = [[NSMutableArray alloc] init];
    else
        newFavorites = [NSMutableArray arrayWithArray:oldFavorites];

    if (isOn)
        [newFavorites addObject:title];
    else
        [newFavorites removeObject:title];

    [userDefaults setObject:newFavorites forKey:kMyFavsKey];

    [userDefaults synchronize];
}

Надеюсь, это исправит вашу проблему.