UITableview不通过willdisplaycell选择单元格

时间:2016-04-29 17:39:28

标签: ios objective-c uitableview

我正在尝试通过加载与他们在传递中单击的单元格对应的数字列表来预先选择tableview中的单元格。我从nsuserdefaults加载它并使用willdisplaycell方法单击单元格。我已经包含了我用来执行此操作的tableviewcontroller类。

@implementation AllergenTableViewController

static NSMutableArray *data;

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        data = [[[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"DictKey"] allKeys] mutableCopy];
        self.allergens = [[NSMutableArray alloc] init];
    }

    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
     self.clearsSelectionOnViewWillAppear = NO;

    //first need to load in array to a number list, then convert it to index path list and set allergens equal to that
    NSMutableArray *allergenNumberList;

    allergenNumberList = [[[NSUserDefaults standardUserDefaults] objectForKey:@"allergens"] mutableCopy];

    if (allergenNumberList != nil)
    {
        for (NSNumber *num in allergenNumberList)
        {
            NSIndexPath *path = [NSIndexPath indexPathForRow:num.integerValue inSection:1]; //[NSIndexPath indexPathWithIndex:num.integerValue];

            if (![self.allergens containsObject:path])
            {
                [self.allergens addObject:path];
            }
        }
    }

    NSLog(@"loading view, allergens size: %lu", [self.allergens count]);
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self.allergens containsObject:indexPath])
    {
        [cell setSelected:YES animated:NO];
    }
}

....

// the cell will be returned to the tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"allergenslabel"forIndexPath:indexPath];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"allergenslabel"];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    }

    cell.textLabel.text = [NSString stringWithFormat:@"%@", data[indexPath.row]];

    return cell;
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSMutableArray *arr = [[NSMutableArray alloc] init];

    for (NSIndexPath *idx in self.allergens)
    {
        [arr addObject:[NSNumber numberWithInteger:idx]];
    }

    [[NSUserDefaults standardUserDefaults] setObject:arr forKey:@"allergens"];
    NSLog(@"saving");
    NSLog(@"allergens count: %lu", [self.allergens count]);
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    //contains isnt working because the index pths arent the same but have the same row numbers so check those instead
    if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
    {
        cell.accessoryType = UITableViewCellAccessoryNone;

        if ([self.allergens containsObject:indexPath])
        {
            [self.allergens removeObject:indexPath];
        }
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;

        if (![self.allergens containsObject:indexPath])
        {
            [self.allergens addObject:indexPath];
            NSLog(@"adding object");
        }
        else
        {
            NSLog(@"object already in allergens list");
        }
    }
}

@end

问题是,当我回到导航控制器并再次前进到tableview时,行没有被选中,但是如果我在导航控制器中向前移动并返回它们将被默认选中(我不会为了这个,我必须做任何事情。

更新

我经历了并排除了一些不太相关的通用方法。

3 个答案:

答案 0 :(得分:1)

当您返回导航控制器时,视图控制器被释放,因此选择哪一行的数据将丢失。导航到此页面将实例化视图控制器的新实例。那不再是你之前见过的那张桌子。当您在导航中前进(在堆栈上抛出新的视图控制器)时,带有表的视图控制器将保留在导航堆栈中,因此数据在您离开时仍然存在。您需要找到其他地方来保存数据并将其传递给这个新实例。

答案 1 :(得分:0)

@Andrew McKinley的答案是完全正确的,所以提供一个解决方案,您可以使用单身人士来保存您选择的单元格。

档案>新>文件>可可类>类:Singleton子类:NSObject

// Singleton.h    

#import <Foundation/Foundation.h>

@interface Singleton : NSObject
+ (Singleton *)shared;
@property (strong, nonatomic) NSMutableArray *allergens;
@end
// Singleton.m

#import "Singleton.h"

@implementation Singleton

static Singleton *sharedInstance = nil;

+ (Singleton*)shared
{
    @synchronized(self)
    {
        if( sharedInstance == nil )
        {
            sharedInstance = [[Singleton alloc] init];
        }
        return sharedInstance;
    }
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.allergens = [[NSMutableArray alloc] init];
    }
    return self;
}

现在您只需将Singleton.h导入AllergenTableViewController类并调用过敏原数组,如:

[[Singleton shared].allergens addObject:@"obj"];

什么是辛格尔顿? “在软件工程中,单例模式是一种设计模式,它将类的实例化限制为一个对象。当需要一个对象来协调整个系统的操作时,这非常有用。” {{3 }}

答案 2 :(得分:0)

所以事实证明我对NSIndexPath的比较或路径转换为数字有问题。我添加了包装器来检查我的过敏原数组中的包含,(不使用NSMutableArray的containsObject:方法和扩展NSIndexPath的isEqual方法,而是使用行比较),现在问题似乎已得到解决。 willDisplayCell:正在调用,当tableview首次加载时我的单元格正在被检查。