最近做这样一个需求:如下图所示,
中间碰到了一个问题,就是
tableView
调用reloadData
方法,但是cellForRowAtIndexPath
不执行,因此记录一下。
一. 例子
//
// ViewController.m
// FJTestProject
//
// Created by fjf on 2017/4/8.
// Copyright © 2017年 fjf. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation ViewController
#pragma mark --- life circle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
self.view.backgroundColor = [UIColor whiteColor];
}
#pragma mark --- system delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 250;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = @"cellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
cell.backgroundColor = [UIColor colorWithRed:arc4random_uniform(256)/256.0 green:arc4random_uniform(256)/256.0 blue:arc4random_uniform(256)/256.0 alpha:1];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 200;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView reloadData];
}
#pragma mark --- private method
// tableView
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
}
return _tableView;
}
@end
这个例子效果如下:
每个cell
的背景色是随机的,当点击任何一个cell
会调用[self.tableView reloadData]
,这样每个cell
的背景色就会更换。
但是当加上下面这段代码:
#pragma mark --- init method
- (instancetype)init {
if (self = [super init]) {
self.tableView.backgroundColor = [UIColor whiteColor];
}
return self;
}
再次点击cell
调用[self.tableView reloadData]
,但不会执行- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
;对应的cell
的背景色也不会变化。
同样的我们给ViewController
添加一个UIColor
的属性,然后通过这个属性设置self.tableView
的背景色
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic, strong) UIColor *backgroudColor;
@end
#pragma mark --- setter method
- (void)setBackgroudColor:(UIColor *)backgroudColor {
self.tableView.backgroundColor = backgroudColor;
}
然后在AppDelegate
里面调用:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
ViewController *tmpViewController = [[ViewController alloc] init];
tmpViewController.backgroudColor = [UIColor redColor];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:tmpViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
效果如下:
同样的,再次点击cell
调用[self.tableView reloadData]
,但不会执行- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
;对应的cell
的背景色也不会变化。
也就是说只要是在- (void)viewDidLoad
之前或者更确切的说是- (void)loadView
之前调用self.tableView
,这样就会导致调用[self.tableView reloadData]
,不会执行- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
;
所以最好保持UIViewController
里面的控件的调用最好是在- (void)viewDidLoad
方法里面或者之后调用。
如果非要在- (void)viewDidLoad
之前或者- (void)loadView
之前调用,最好先调用一下self.view
这样就会保证先去调用- (void)loadView
,方法这样也可以保证[self.tableView reloadData]
不会受到影响。
#pragma mark --- setter method
- (void)setBackgroudColor:(UIColor *)backgroudColor {
self.view.backgroundColor = backgroudColor;
self.tableView.backgroundColor = backgroudColor;
}
效果如下:
二. 原因
具体导致这个问题产生的原因,我也找了很久也没找到合理的解释,希望懂得的朋友能给出您宝贵的看法。
三.最后
送上一张图片: