5

高度にカスタマイズされた、または複雑なビューを持つアプリケーションを考えてみましょう。

特定の種類のビュー コントローラーが特定の種類の UIView にメソッドを送信するようにします。UIView 自体は多数の他のビューで構成されています。

ビューには、ドメイン固有のリッチなインターフェイスが必要です。これにより、コントローラーが機能できるようになり、ビューと同様にリッチなモデルの間の薄い「接着剤」レイヤーになります。

したがって、コントローラーのビュー プロパティを次のようにオーバーライドします。

@interface PlaybackViewController : UIViewController<StageLayoutDelegate, ControlPanelDelegate>
{
    NSMutableArray* _sections;
    LightingMode _lightingMode;
}

@property (nonatomic, strong) PlaybackView* view; // <------ Specific type of view

#pragma mark - injected
@property (nonatomic, strong) id<OscClient> oscClient;
@property (nonatomic, strong) AbstractStageLayoutView* stageLayoutView;

@end

オーバーライドは、別のアクセサーを定義するよりも理にかなっています。また、キャストすることなく、特定のタイプの UIView にメッセージを送信するだけで済みます。

問題:唯一の問題は、コンパイラの警告が発生することです。

プロパティ タイプ 'PlaybackView *' は、'UIViewController' から継承されたタイプ 'UIView *' と互換性がありません

. . 警告のないコードを作成するのが好きです。このようにして、有効な警告が他の警告に埋もれて見逃されることはありません。

質問:

  • この特定の警告を抑制する方法はありますか?
  • 最近のほとんどのオブジェクト指向言語では、スーパークラスで宣言された型のより具体的なサブクラスを返すように、サブクラスのプロパティまたはメソッドを喜んでオーバーライドできるのに、なぜこれがデフォルト設定の一部なのですか?
4

5 に答える 5

8

ここでの問題は、プロパティのオーバーライドではなく、クラス型の前方宣言を使用していることです。

したがって、この...

@class PlaybackView;

@interface PlaybackViewController : UIViewController

@property (nonatomic, strong) PlaybackView* view;

@end

コンパイラは の継承階層を認識できないため、前述の警告が表示されますPlaybackView。その財産からUIViewController提供する契約を結んでいるUIViewview

PlaybackViewそれはそうではないと考えていることをあなたに伝えていますUIView

ここでの簡単な解決策は、#import代わりに a を使用して、コンパイラにPlaybackView...の完全な知識を与えることです。

#import "PlaybackView.h"

@interface PlaybackViewController : UIViewController

@property (nonatomic, strong) PlaybackView* view;

@end

代わりに(ただし、PCHは最適化機能であり、依存関係を管理すべきではないため、本当に悪い形式です)#import "PlaybackView.h"、プロジェクトにPCHを追加することです

于 2014-05-05T13:51:05.317 に答える
0

UIViewControllers ビュー プロパティをオーバーライドするのは良い方法ではないと思います。

私はこのようにする方が良いと思います:

@interface PlaybackViewController : UIViewController<StageLayoutDelegate, ControlPanelDelegate>
{
    NSMutableArray* _sections;
    LightingMode _lightingMode;
}

//@property (nonatomic, strong) PlaybackView* view; //you do not need this property

#pragma mark - injected
@property (nonatomic, strong) id<OscClient> oscClient;
@property (nonatomic, strong) AbstractStageLayoutView* stageLayoutView;

@end

および .m ファイルにあります。

- (void)loadView
{
    PlaybackView *mainView = [[PlaybackView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    // set the mainView
    self.view = mainView;
}

PlaybackView をこのように使用できます。

((PlaybackView *)(self.view)).oscClient

また

((PlaybackView *)(xxxViewControler.view)).oscClient
于 2013-02-05T02:21:17.267 に答える
0

おそらく、ある意味で、キャストを提供する別のメソッドを宣言することもできます。

@implementation PlaybackViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //  use view_ property instead of view
    self.view_.foo = 1;
}

- (void)loadView {
    CGRect frame = [UIScreen mainScreen].applicationFrame;
    self.view = [[PlaybackView alloc] initWithFrame:frame];
}

- (PlaybackView *)view_ {
    return (PlaybackView *)self.view;
}

正確には最もクリーンなアプローチではありませんが、キャストを回避しますself.view(ただし、を使用しないことによりself.view

于 2014-05-05T10:45:21.433 に答える