【问题标题】:UIViewController, UITableView subclassing - my solution feels dirtyUIViewController,UITableView 子类化 - 我的解决方案感觉很脏
【发布时间】:2012-04-18 23:41:36
【问题描述】:

我的项目中有许多 UIViewController 实现了 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 之一时,它工作得很好。

但是,我有六个这样的 UIViewController,它们都被划分为不同的类,实现不同的功能。所以我决定在我的子类 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

看起来有点奇怪,在两个地方都有外观代码,但总比把相同代码的副本分散在各处要好。在 FooDetailsViewController 中,我实现了一些 Table Protocol 方法,但没有实现 viewForHeaderInSection。我还在 FFViewController 上收到警告,因为它没有实现所有协议(这是故意的,本示例中的子类 FooDetailsViewController 填写了协议。)

那么问题是什么?

并非所有其他子类 UIViewController 都响应 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. 我的外观代码在 2 个不同的类别中
  3. 我需要在不需要的代码中实现 titleForHeaderInSection,因为它没有节标题

(感谢您阅读本文!)

【问题讨论】:

  • 如果你误解了你,我真的很抱歉。你能告诉我所有拥有 UITableView Delegate 的控制器是否有相同类型的单元格,我的意思是在大小上以及这些单元格上的文本是什么...... ..
  • @Addicted:我想你有一个你自己想问的问题。只需创建一个新问题。
  • 我应该知道这是什么意思
  • 对不起。我不明白你的第一条评论。我不知道你为什么要问我这些问题。它们似乎不相关。我猜测您有自己的技术问题,您希望我对您的评论的回答对您有所帮助。我不明白这怎么可能。所以,如果你有问题,就问吧。点击页面右上角的“”链接。

标签: ios uitableview


【解决方案1】:

在您的respondsToSelector 代码中,您为正在测试的选择器提供了错误的名称。应该是:

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

如果您进行了该更改,您的测试应该可以工作,然后您的子类可以选择实现 tableView:titleForHeaderInSection: 或不实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 2021-10-31
    • 2015-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    相关资源
    最近更新 更多