最近做这样一个需求:如下图所示,

中间碰到了一个问题,就是
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;
}
效果如下:

二. 原因
具体导致这个问题产生的原因,我也找了很久也没找到合理的解释,希望懂得的朋友能给出您宝贵的看法。
三.最后
送上一张图片:
