1

XCode 4.3.3 を使用した単純な「シングル ビュー」テスト プロジェクトでは、次のようになります。

  1. UIView をサブクラス化し、ストーリーボードのプロパティ インスペクターで、viewController の既定のビューとして使用するクラスとして指定しました。

  2. カスタム UIView クラスでTestUIView、「drawSwitch」というプロパティを定義します。

  3. カスタム クラスのヘッダーを viewController クラスにインポートします。

プロジェクトをコンパイルしようとすると、次のコード行でコンパイラがサブクラスを認識せず、次のエラーが発生することに驚きました: Property 'drawSwitch' not found on object of type 'UIView' . カスタム クラスTestUIViewが viewControllerviewアウトレットのクラスとして示されているため、これは奇妙に思えます (下の画像を参照)。

[self.view setDrawSwitch:2];

それでも、キャストすると、コードはコンパイルされ、正常に実行されます。

[(TestUIView*) self.view setDrawSwitch:2];

viewController のプロパティを表示すると、カスタム クラスがビュー プロパティの Outlet として示されます。

そのため、ここのストーリーボードで何が起こっているのか混乱しています。

  • ストーリーボード/XCode を使用すると、コンパイラが満足できないことを実行できますか? GUI の抜け道ですか?

  • カスタム ビュー用に IBOutlet を作成できることはわかっていますが (以下では「testView」)、viewアウトレットが既に定義されている場合に追加のアウトレットを作成するのは冗長に思えます。

ここで何か不足していますか?(「それが機能する方法」を超えて、実際にそうである可能性があります)。

ここに画像の説明を入力

4

2 に答える 2

2

コンパイラは、ストーリーボードに何を設定したかについては何も知りません。わかっているのは、ViewControllerの.viewプロパティがUIViewになるということだけです。実行時にUIViewの任意のサブクラスをこのプロパティに問題なく割り当てることができるため、これは正常に機能します。

より具体的なサブクラスであるかのようにviewプロパティを使用しようとすると、問題が発生します。コンパイラは、実行時に、UIViewが実際には別のクラスであると見なしていることを認識していません。

あなたの「冗長な」アウトレットは、実際にはAppleがUITableViewControllerでこの状況を実装した方法です。UITableViewControllerには.view.tableViewプロパティがあり、これらは両方ともまったく同じオブジェクト(テーブルビュー)を指します。

別の方法は、ここここで説明するように、プロパティをオーバーライドして別のクラスを作成することですが、これはViewControllerで予期しない影響を与える可能性があります。より具体的なクラスを持つ別のプロパティに固執することをお勧めします-それは確かにあなたのコードをより読みやすくします。

オフトピック-これはStackOverflowに関する私の1000番目の答えです-どういたしまして!

于 2012-07-29T12:25:07.740 に答える
0

あなたが投稿していないかもしれないが間違っているか、私が問題を正しく理解していなかったかもしれない何かがあります。

私が試した簡単な例は、拡張されたものとして機能し、キャストは不要で、ストーリーボードを介して簡単に使用できます。

したがって、SVTView.hのコードは次のとおりです。

@interface SVTView : UIView{

}
-(void)sampleSet:(int)value;


@end

およびSVTView.m:

#import "SVTView.h"

@implementation SVTView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

-(void)sampleSet:(int)value{
  NSLog(@"setting value %d",value);
}


@end

そして最後に、ViewController内での使用法:

#import <UIKit/UIKit.h>
#import "SVTView.h"

@interface SVTViewController : UIViewController{

  IBOutlet SVTView * testView;
}

@property(nonatomic, retain) SVTView * testView;

@end

そしてViewcontroller.m:

#import "SVTViewController.h"

@interface SVTViewController ()

@end

@implementation SVTViewController

@synthesize testView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
  [testView sampleSet:2];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
  return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

参照するアウトレットはストーリーボードを介して接続されているため、インスタンス変数が使用されます。ログコンソールには、表示されない結果が表示されます。

2012-07-28 07:51:02.227 SingleViewTest[1490:f803] setting value 2

正しいクラスを使用することは冗長ではありません。冗長な部分はおそらくクラスキャストです。

于 2012-07-28T05:56:56.050 に答える