2026-06-25 19:51:52
UITableView占位图的低耦合性设计需围绕显示条件、首次加载干扰排除、网络失败处理及再次请求策略展开,以下是具体方案:
1. 需要显示占位图的情况tableView.sections > 0且tableView.rows == 0;
tableView.viewForHeaderInSection != nil(即存在自定义的sectionHeaderView)。
需求场景:点击sectionHeaderView展开section并刷新数据,此时若仅判断rows == 0会导致占位图异常显示。
属性标记法:在UITableView分类中添加BOOL属性isNotFirstReload,默认值为NO。
在reloadData方法内部判断:
if (self.isNotFirstReload) { [self checkEmpty]; // 检查是否显示占位图} self.isNotFirstReload = YES;优势:无需外部传入参数,避免遍历子视图带来的性能损耗。
避免的方案:
遍历子视图:通过递归遍历控制器子视图查找UITableView并设置属性,但性能开销较大,尤其在视图启动时。
统一处理法:通过window的rootViewController获取当前控制器,遍历其子视图找到UITableView并调用reloadData。
代码示例:
// 获取根控制器UIViewController *rootVC = [[[UIApplication sharedApplication] delegate] window].rootViewController;// 处理导航控制器情况if ([rootVC isKindOfClass:[UINavigationController class]]) { UIViewController *visibleVC = [(UINavigationController *)rootVC visibleViewController]; [self findTargetViewWithController:visibleVC];} else { [self findTargetViewWithController:rootVC];}// 遍历子视图- (void)findTargetViewWithController:(UIViewController *)viewController { NSArray *subViews = viewController.view.subviews; [subViews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { if ([view isKindOfClass:[UITableView class]]) { UITableView *tableView = (UITableView *)view; [tableView reloadData]; } }];}局限性:
性能损耗:遍历子视图需一定时间,但因仅在请求失败时触发,影响较小。
多请求干扰:若界面存在多个请求,任一请求失败可能误触发其他tableView的reloadData。
基类统一处理:
懒加载tableView:在基类中初始化tableView并设置代理(如reRequestDelegate)。
代理回调:定义协议方法(如reRequesData),在回调中调用统一的网络请求方法(如loadData)。
子类重写:子类仅需实现loadData方法完成具体网络请求逻辑。
代码示例:
// 基类中- (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectZero]; _tableView.delegate = self; _tableView.reRequestDelegate = self; // 设置代理 } return _tableView;}- (void)reRequesData { [self loadData]; // 调用统一方法}// 子类中- (void)loadData { // 实现具体网络请求}优势:
代码复用:子类无需重复实现点击事件处理逻辑。
低耦合:占位图触发逻辑与业务逻辑分离,便于维护。