每个 controller 里面一般都会实现 viewDidLoad 和 viewWillAppear: 两个方法。对于iOS开发人员来说,这两个方法都很熟悉。至少都知道前者是在初始化时被调用一次,后者是在每次这个视图要被显示之前被调用一次。因此 controller 中主要的初始化代码都放在前者中,而后者主要用于视图在显示前的更新。但现实情况并不是这么理想,因为我们在 viewDidLoad 方法中获取到一些数据并不是准确的,特别是视图相关的数据,因为很可能其他视图此时并没有完成初始化。因此只好将某些初始化工作也放到 viewWillAppear: 方法中,但是控制它只执行一次。以下用一点代码片段来举例,我的应用中有个收藏视图,使用 UITableView 做的,用户收藏的文章可以以列表形式展示在这里。当收藏为空时会展示一个带图片的提示视图,当点击这个视图任何位置时会跳转到文章目录。需求就是这样,代码片段如下。
//空白提示视图(emptyView)的初始化方法
- (void)initEmptyView {
//emptyView 为本类的实例变量,将它的位置和大小设为与tableView一样,以便正好覆盖。这段代码如果是在 viewDidload 中被调用就会有问题,
//获取 tableView 的尺寸信息不准,在 viewWillAppear 中被调用就没问题。
emptyView = [[UIControl alloc] initWithFrame:self.tableView.frame];
emptyView.backgroundColor = [UIColor clearColor];
//添加一个带图片视图到 emptyView 中,并将图片视图居中
UIImageView *noCollectImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"no_collect.png"]];
[emptyView addSubview:noCollectImgView];
[noCollectImgView setCenter:CGPointMake(emptyView.bounds.size.width / 2, emptyView.bounds.size.height /2)];
//为 emptyView 添加点击事件
[emptyView addTarget:self action:@selector(emptyViewClicked) forControlEvents:UIControlEventTouchUpInside];
}
//空白提示视图点击后被调用
- (void)emptyViewClicked {
[self.tabBarController setSelectedIndex:0];
}
//空白提示视图的展示与隐藏逻辑
- (void)handleEmpty {
if (!emptyView) {
[self initEmptyView];
}
if (![self.tableView.superview.subviews containsObject:emptyView]) {
[self.tableView.superview addSubview:emptyView];
}
//判断表格中是否为空
int num = [self tableView:self.tableView numberOfRowsInSection:0];
if (num > 0) {
emptyView.hidden = YES;
} else {
emptyView.hidden = NO;
self.navigationItem.rightBarButtonItem = nil;
}
}
- (void)viewWillAppear:(BOOL)animated {
[CoreDataContext performCollectFetch];
[self.tableView reloadData];
//空白提示视图展示与否的逻辑
[self handleEmpty];
}