UIViewController,UITableView子类化 - 我的解决方案感觉很脏

时间:2012-04-18 15:31:10

标签: ios uitableview

我的项目中有许多UIViewControllers,它们实现了UITableViewDataSource和UITableViewDelegate协议。在Interface Builder中,我删除了UIView并将其替换为子类UITableView。在我的子类UITableView中,我设置了一个自定义backgroundView。

    @interface FFTableView : UITableView
    @end

    @implementation FFTableView

    - (id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder]; // Required. setFrame will be called during this method.

        self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];;

        return self;
    }

    @end

一切正常。我有六个左右的UIViewControllers都有子类UITableViews,它们都绘制了我的背景图像。我的背景图片很暗,所以我需要绘制我的节标题以便它们可见。谷歌搜索我找到How to change font color of the title in grouped type UITableView?,我在我的子类中实现了viewForHeaderInSection。

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {
        ...

我的viewForHeaderInSection未被调用。当然,当我想了一会儿时,这是有道理的。我的UIViewControllers是实现UITableViewDataSource和UITableViewDelegate的对象,当我将viewForHeaderInSection放在我的一个UIViewControllers中时,它的工作正常。

但是,我有六个这样的UIViewControllers,它们都被子类化到不同的类,实现了不同的功能。所以我决定在我的子类UIViewControllers和UIViewController之间放一个类。这样设置节标题外观的常用代码将在一个位置,而不是在六个位置。

所以我写道:

    @interface FFViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
    @end

在这里我实现了viewForHeaderInSection:

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {

        NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
        if (sectionTitle == nil) {
            return nil;
        }
        ...

并将我的其他子类控制器更改为FFViewController,这里是一个:

    @interface FooDetailsViewController : FFViewController

看起来有点奇怪,外观代码在2个地方,但它比分散在同一地方的相同编码的副本更好。在FooDetailsViewController中,我实现了一些表协议方法,但没有实现viewForHeaderInSection。我也在FFViewController上收到警告,因为它没有实现所有协议(这是有意的,本例中的子类,FooDetailsViewController,填写协议。)

那么问题是什么?

并非所有其他子类UIViewControllers都会响应titleForHeaderInSection,因此当我运行时,我会在这些视图控制器上崩溃。所以我试着看看是否实现了titleForHeaderInSection:

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {
        if (![self respondsToSelector:@selector(titleForHeaderInSection)]) {
            return nil;
        }

        NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
        if (sectionTitle == nil) {
            return nil;
        }

且respondsToSelector始终返回false。所以我可以杀死那个部分并强制所有子类实现titleForHeaderInSection,但这似乎是错误的。

出现这种情况有什么好办法?我已经不喜欢这个解决方案,因为:

  1. 代码有警告。 (但我总是可以How to avoid "incomplete implementation" warning in partial base class阻止他们)
  2. 我的外观代码分为两个单独的类
  3. 我需要在不需要它的代码中实现titleForHeaderInSection,因为它没有节标题
  4. (感谢您阅读此内容!)

1 个答案:

答案 0 :(得分:2)

在您的respondsToSelector代码中,您为要测试的选择器指定了错误的名称。它应该是:

if (![self respondsToSelector:@selector(tableView:titleForHeaderInSection:)]) {
    return nil;
}

如果您进行了更改,那么您的测试应该可行,您的子类可以选择性地实现tableView:titleForHeaderInSection: