0

これについての基本を忘れているようです。それとも、疲れすぎているのかもしれません。

ビューコントローラーと、そのサブクラスでUIViewある MyViewClass という名前のビューがあります。

viewDidLoad私のviewControllerでは、私は次allocinit self.myViewようにしています:

self.myView = [[MyViewClass alloc] initWithFrame:(CGRect){{0, 0}, 320, 480}];
self.view = self.myView;

私のviewControllerのある時点で、私は[self.view setNeedsDisplay];. ここでは問題ありません。

MyViewClass.h でプロパティを公開します。

@property(nonatomic) i;

プロパティはmyViewiで使用されます。drawRectしたがって、私のviewControllerから次のように設定します。

self.myView.i = 100;

だから私の質問は:

[self.view setNeedsDisplay];呼び出す必要なくビュー コントローラーを呼び出すことができ、myView で呼び出されるのに、既にビュー コントローラーに割り当てられているようにビュー コントローラーで呼び出すことができない[self.myView setNeedsDisplay];のはなぜですか?drawRectself.view.iself.myViewself.viewviewDidLoad

4

3 に答える 3

2

を呼び出すことはできますが、のプロパティがタイプであるため、呼び出すことはでき[self.view setNeedsDisplay]ません。self.view.iUIViewControllerviewUIView

self.myView はすでに viewDidLoad にある self.view に割り当てられています

実際の代入は実行時に発生しますが、コンパイラ エラーはコンパイル時に生成されることに注意してください。コンパイラは、View Controller のメソッドが呼び出される順序を認識していないため、プロパティの元の宣言を超えてプロパティの値の実際の型を推測することはできません。Xcodeに関する限り、self.viewは単なるUIView.

上でダンが提案したように、プロパティ宣言をオーバーライドして、ビューのタイプがMyView. とにかく、プロパティを使用するアプローチself.myViewが好まれる場合があります。これにより、インターフェイスを変更せずに将来ビュー階層を変更でき、継承されたメソッドをいじることがありません。とプロパティUITableViewControllerは同じビュー インスタンスを返しますが、プロパティの型が異なります。viewtableView

プロパティの型は必ずしもそのの型と同じではないことに注意してください。self.viewのインスタンスに割り当てられている可能性がありますMyViewが、プロパティのタイプは のままですUIView。割り当てられたオブジェクトの型に関係なく、プロパティのアクセサーは戻り値の型を持つメソッドUIViewです。

したがって、コンパイラに関する限り、そうではないことがわかっていてもself.view、 は単純な古いにすぎません。UIView

プロパティとは何かについて詳しく説明し、プロパティとインスタンスを区別すると役立つと思います。次のようなプロパティを作成する場合:

@interface MyViewController : UIViewController

@property(strong, nonatomic) MyView *myView;

@end

コンパイラは、それを変数、アクセサ メソッド ("getter")、および mutator メソッド ("setter") に変換します。プロパティは、次のようにメソッドを宣言するための単なる省略形です。

@interface MyViewController : UIViewController
{
    MyView *_myView;
}

- (MyView *)myView; // accessor / getter
- (void)setMyView:(MyView *)myView; // mutator / setter

@end

@implementation MyViewController

- (MyView *)myView
{
    return _myView;
}

- (void)setMyView:(MyView *)myView
{
    _myView = myView;
}

@end

self.myView、またはを呼び出すときself.viewは、実際にはアクセサ メソッドを呼び出しています。[self myView]またはと同等[self view]です。返されるのは、メモリ内のオブジェクトへのポインターです。を割り当てたのでself.view = self.myView、両方のプロパティが同じオブジェクトに設定されます。したがって、両方とも同じオブジェクトへのポインタを返しますself.viewself.myView

要約する:

  • は のサブクラスであるため、代入self.view = self.myViewはコンパイル エラーを生成しません。のサブクラスではないため、代入すると警告が生成されることに注意してください。MyViewUIViewself.myView = self.view UIViewMyView
  • 同じインスタンスが両方のプロパティに割り当てられているため、呼び出す[self.view setNeedsDisplay]myView、それ自体が描画されます。両方のプロパティの説明 ( ) をログに記録すると、それらのメモリ アドレスが同じであることがわかります。NSLog(@"view=%@, myView=%@", self.view, self.myView)
  • プロパティがタイプを持つように宣言されており、という名前のメソッドがないself.view.iため、呼び出すことができません。viewUIViewUIViewi
于 2014-01-30T20:45:03.583 に答える
1

viewController の viewDidLoad で、次のように self.myView を割り当てて初期化します。

self.myView = [[MyViewClass alloc] initWithFrame:(CGRect){{0, 0}, 320, 480}];
self.view = self.myView;

絶対に絶対にしないでくださいviewDidLoadviewDidLoadすでにビューがあることを意味します。ビュー コントローラーのビューを決して変更しないでください。

ビューを設定することは問題ありません (必須です) loadView。それが目的です。しかし、viewDidLoadでは、絶対にありません。

于 2014-01-30T20:11:14.780 に答える
0

VCs ビューを UIView サブクラスに置き換えようとしていますが、通常どおりに動作させるだけでなく、VC のコードがサブクラスのプロパティにアクセスできるようにしますか? ビューゲッターをオーバーライドすることでそこに到達できると思います:

- (MyView *)view {
    return (MyView *)[super view];
}

また、VC のビューとして IB でカスタム ビューをセットアップできるため、loadView で何もする必要はありません。

于 2014-01-30T20:23:51.083 に答える