4

単一のUIWebViewを担当するUIViewControllerのサブクラスがあります。

-(void)loadViewこれは単純なケースなので、UIWebViewをオーバーライドしてインスタンス化し、コントローラーのviewプロパティを割り当てます。

- (void)loadView 
{
    UIWebView *wv = [[[UIWebView alloc] initWithFrame:self.frame] autorelease];
    // other configuration here...  
    self.view = wv;
}

UIWebViewのメソッドを呼び出すまではこれで問題ありません。例えば...

[self.view loadHTMLString:HTMLString baseURL:baseURL];

...コンパイラの警告につながります...

warning: 'UIView' may not respond to '-loadHTMLString:baseURL:'

...viewプロパティがとして宣言されているためUIView

、警告はキャストで簡単に解決されます...

[(UIWebView *)self.view loadHTMLString:HTMLString baseURL:baseURL];

...しかし、私がやりたいのは、インターフェイスに正しいタイプのヒントを提供することです。viewでプロパティをオーバーライドしようとしましたMyViewController.hが、これもコンパイラを混乱させます。

warning: property 'view' type does not match super class 'UIViewController' property type

これが私がしていることであり、これが私がしていることであり、すべて大丈夫であることを私が知っていることをコンパイラー(および私の仲間)に伝える方法はありますか?(そうでない場合は、キャストに固執すると思います。)

TIA

編集: marcus.ramsdenの答えに従ってビュープロパティを再宣言しようとしました:これにより警告(およびキャストの必要性)がなくなりましたが、ビューがまったく表示されなくなりました!コントローラーが要求されたときにUIView(サブクラス)を返すので、なぜこれが必要なのかわかりません...

4

6 に答える 6

5

簡単な答えは、これを行うための合理的な方法がないということです。そして、それを行うための不合理な方法を見つけることは、それが解決するよりも多くの問題を生み出すでしょう。これはあなたが望む答えではないことを私は理解していますが、将来この質問を読む人のために、なぜあなたがこれをすべきではないと私が信じているのかを説明します。

viewプロパティはUIViewControllerのパブリックインターフェイスの一部であり、戻り値の型はそのインターフェイスの一部です。サブクラス化したクラスのパブリックインターフェイスを変更するのは臭いです。それがあなたにとって十分な理由ではない場合は、ViewControllerのviewプロパティがUIKitの基本的なビットであると考えてください。フレームワークにより体系的な影響を与える可能性のある、混乱する可能性のあるものはほとんどありません。そのシンプルなインターフェースゲッターのファサードの下にどんな種類の暗い策略があるのか​​誰が知っていますか?すでにここに残されているコメントのいくつかに基づいて、このプロパティを再定義すると、明らかな方法で物事が壊れるように見えます。私は遠ざかります。

rubyのような言語を使用している場合、コンパイラの警告なしにviewプロパティによって返されるオブジェクトに任意のメッセージを送信できないという事実は、おそらく満足のいくものではないように思われます。ただし、良くも悪くも、Objective Cは静的に(特に強くはないにしても)型付けされた言語です。特定のツールを使用しているときは、別のツールのイディオムに靴べらをかけるのではなく、そのツールの長所に取り組み、その短所を回避することをお勧めします。

一方、C ++のような強く型付けされた言語から来た場合、そのキャストも非常に満足のいくものではないと感じるはずです。キャストは、静的に型付けされた言語が大きく依存する型システムを覆し、ほとんどの場合、厄介なコードの臭いです。CスタイルのキャストはCタイプシステムの核兵器です。それらは絶対にすべてをオーバーライドし、ほとんどの場合、使用するのは間違っています。

将来、Webビューとともにビューにラベルを追加することにした場合はどうなりますか?その場合、Webビューをサブビューに移動する必要があります。ただし、View ControllerのベースビューをどこでもUIWebViewにキャストしている場合、キャストは嘘になります。残念ながら、Cスタイルのキャストはチェックされていないため、コンパイラはそれらの嘘を見つけるのに役立ちません。UIView、int、ブロック、関数ポインター、またはサイからUIWebViewを作成でき、コンパイラーはのぞき見をしません。ただし、アプリは大幅にクラッシュします。

最後に、複雑さを回避することに関心があると言います。Webビューをベースビューのサブビューとして追加するには、単一のプロパティを宣言(および合成)して、viewDidLoadにサブビューを追加するだけでよいことを考慮してください。少しの労力を考えると、Webビューへのすべての呼び出しは次のようになります。

[self.webView loadHTMLString:HTMLString baseURL:baseURL];

または、キャストに固執する場合、Webビューへの各呼び出しは次のようになります。

[(UIWebView *)self.view loadHTMLString:HTMLString baseURL:baseURL];

前者は私にはそれほど複雑ではなく、もろくないようです。

于 2010-11-30T20:04:07.397 に答える
2

プロパティを定義できます

@property (nonatomic, readonly) UIWebView *webView;

そしてこれを行う:

- (UIWebView*)webView {
   return (UIWebView*)self.view;
}

- (void)loadView 
{
    UIWebView *wv = [[[UIWebView alloc] initWithFrame:self.frame] autorelease];
    // other configuration here...  
    self.view = wv;
}

その後self.webView、キャストせずにWebViewにアクセスできます。基本的に、キャストをコード内の1つの特定の場所に集中化しています。ラベルのような別のビューを挿入したい場合は、コード内の1つの場所を変更するだけです。

于 2010-12-03T09:51:01.900 に答える
2

viewこれはサブクラスであるため、プロパティ/メソッドをオーバーライドして。にすることができますUIWebView。aUIWebViewはのサブクラスでありUIView、あなたがサブクラスの唯一のユーザーであるため、これは完全に安全であるはずです。

@interface MyAbstractViewController : UIViewController {
    UIWebView *_webView;
}
@property (nonatomic, retain) UIWebView *view;
@end

@implementation MyAbstractViewController    
@dynamic view;
- (void)setView:(UIWebView *)webView {
  [super setView:webView];
  _webView = webView;
}

- (UIWebView *)view {
  return _webView;
}
@end
于 2010-11-30T14:40:55.100 に答える
0

ドキュメントから、カテゴリを使用してやりたいことができるように見えます。例えば;

// UIWebViewController.h
@interface UIWebViewController : UIViewController {

}

@end

@interface UIWebViewController ()

@property (nonatomic,retain) UIWebView *view;

@end

// UIViewController.m
@implementation UIWebViewController

@synthesize view;

- (void)viewDidLoad {
    UIWebView *wv = [[UIWebView alloc] initWithFrame:webViewFrame];
    self.view = wv;
    [self.view loadHTML:@"<h1>Hello World</h1>" baseURL:baseURL];
    [wv release];
}

@end

これについては、http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.htmlの[Declared Properties]> [Using Properties]>[PropertyRe-declaration]に少しあります。

これを試してみましたが、コンパイラからの苦情はありませんでした。

于 2010-11-24T10:08:40.653 に答える
0

値をキャストするか、新しいUIWebViewインスタンス変数をviewControllerに追加します。

使用したサブクラスの種類をフェローに通知するのは、UIViewControllerのviewメソッドの仕事ではありません。

やりたいことができれば、UIKitがUIViewControllerのviewメソッドがUIViewを返すことを期待しているすべての場所でUIViewにキャストバックする必要があります。

于 2010-11-30T13:52:51.793 に答える
-1

すでに述べたように、これを行うことは可能ですが、賢明な場合とそうでない場合があります。

UIView自体でカテゴリを宣言して、呼び出そうとしているセレクターに応答する可能性があることを示唆することができます。これは、カスタムViewControllerの実装ファイルで実行できます。次のようになります。

@interface UIView (WebViewFakery)

- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL

@end

呼び出そうとしているすべてのUIWebViewメソッドを追加する必要がありますview。おそらく最も洗練された解決策ではありませんが、考慮すべき別の解決策です。

于 2010-11-30T20:22:27.977 に答える