UITableview 不通过 willdisplaycell 选择单元格

Posted

技术标签:

【中文标题】UITableview 不通过 willdisplaycell 选择单元格【英文标题】:UITableview not selecting cells through willdisplaycell 【发布时间】:2016-04-29 17:39:27 【问题描述】:

我正在尝试通过加载与他们在传递中单击的单元格相对应的数字列表来预选表格视图中的单元格。我从 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 时,未选择行,但如果我在导航控制器中前进并返回,默认情况下会选择它们(我不不必为此做任何事情)。

更新:

我检查并排除了一些不相关的通用方法。

【问题讨论】:

你能把断点放在 data = [[[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"DictKey"] allKeys] mutableCopy];线。当您返回导航控制器并再次前进到表格视图时。并更新推送 Table VC 的代码。 【参考方案1】:

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

【讨论】:

我明白这一点,这就是为什么我将数据保存到 NSUSERDEFAULTS 并在初始化时从那里加载,然后将其加载到 tableview 中。有人告诉我“- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath ”会自动被调用,所以我在这里设置选定的单元格并检查它们是否在我的数组中 很奇怪你正在为 uiviewcontroller 使用 initWithCoder。您确定正在调用该方法吗?您是否有理由不想在 viewDidLoad 中这样做? 是的,我记录了它,老实说,我并没有真正考虑过我是 ios 开发新手。 你是否一直到 [cell setSelected:YES animated:NO];第二次,它仍然没有突出显示?【参考方案2】:

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

文件>新建>文件>可可类>类:单例子类: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 类并调用 allergens 数组,如下所示:

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于UITableview 不通过 willdisplaycell 选择单元格的主要内容,如果未能解决你的问题,请参考以下文章

UITableView不显示任何单元格

带有 UITableView 的 UIToolBar - 加载时 TableView 不刷新

不调用UITableView Delegate

通过点击状态栏滚动到 UITableView 的顶部

当上边距不完全可见时,UITableView 单元格展开动画会发生变化

iPhone 5 UITableView 不显示