0

プロジェクトには、UITableViewDataSourceプロトコルとUITableViewDelegateプロトコルを実装するUIViewControllerがいくつかあります。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

これはすべて正常に機能します。私はこれらのUIViewControllerを半ダースほど持っており、それらはすべてUITableViewsをサブクラス化しており、それらはすべて私の背景画像を描画します。背景画像が暗いので、セクションヘッダーが見えるように描画する必要があります。グーグル私はグループ化されたタイプUITableViewでタイトルのフォントの色を変更する方法を見つけましたか?そして、サブクラスにviewForHeaderInSectionを実装します。

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

私のviewForHeaderInSectionは呼び出されません。もちろん、ちょっと考えてみると理にかなっています。私のUIViewControllersは、UITableViewDataSourceとUITableViewDelegateを実装するオブジェクトであり、UIViewControllersの1つにviewForHeaderInSectionを配置すると、正常に機能します。

しかし、私はこれらのUIViewControllerを半ダース持っており、すべてが異なるクラスにサブクラス化されており、異なる機能を実装しています。そこで、サブクラス化されたUIViewControllersとUIViewControllerの間にクラスを配置することにしました。このように、セクションヘッダーの外観を設定する一般的なコードは、半ダースのスポットではなく、1つのスポットになります。

だから私は書く:

    @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がプロトコルに入力します)。

それで、質問は何ですか?

他のサブクラス化されたUIViewControllerのすべてがtitleForHeaderInSectionに応答するわけではないので、もちろん、実行すると、それらのViewControllerでクラッシュします。だから私は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. コードには警告があります。(しかし、部分的な基本クラスで「不完全な実装」の警告を回避してそれらを停止する方法はいつでも実行できます)
  2. 私の外観コードは2つの別々のクラスにあります
  3. セクションヘッダーがないため、titleForHeaderInSectionを必要としないコードに実装する必要があります

(ここまで読んでくれてありがとう!)

4

1 に答える 1

2

コードで、respondsToSelectorテストしているセレクターに間違った名前を付けました。そのはず:

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

その変更を行うと、テストが機能するはずであり、サブクラスはオプションで実装するtableView:titleForHeaderInSection:かどうかを指定できます。

于 2012-04-18T15:41:36.183 に答える