0

改訂...

アプリの核心は、データベース サーバーとの通信です。サーバーからアプリへの応答はすべて XML です。いくつかの画面があります。たとえば、画面 1 にはユーザーの情報が一覧表示され、画面 2 にはユーザーの過去の取引が一覧表示され、新しい取引が許可されます。

ここに私の AppDelegate からのいくつかのコードがあります:

StartViewController *svc = [[StartViewController alloc] init];
TradeViewController *tvc = [[TradeViewController alloc] init];
CashViewController *cvc = [[CashViewController alloc] init];
ComViewController *covc = [[ComViewController alloc] init];
PrefsViewController *pvc = [[PrefsViewController alloc] init];

NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:5];
UITabBarController *tabBarController = [[UITabBarController alloc] init];

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:svc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:tvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:cvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:covc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:pvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

[tabBarController setViewControllers:tabBarViewControllers];

[[self window] setRootViewController:tabBarController];

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

MVC スタイルに固執しようとして、すべての「処理」を行うシングルトン クラスがあります。

壁にぶつかった例です。ユーザーは画面 5 で電子メール アドレスを変更できます。新しい電子メール アドレスをテキスト フィールドに入力し、保存ボタンをクリックします。次に、ボタンはシングルトン クラスからメソッドを呼び出します。このメソッドは新しい電子メール アドレスをサーバーに送信し、(URL を介して) 変更を確認する XML 応答を受信します。

ここに私の問題があります: 1. シングルトン クラス メソッド呼び出しを行う前に、View Controller からスピナーを開始します - しかし、アプリからサーバーへの送受信がいつ終了するかわかりません。適切なタイミングでスピナーを停止するにはどうすればよいですか? 私はシングルトンクラスからそれをすることはできません、私はそれを試しました. 私が知っていることから、それはVC内からでなければならないか、またはシングルトンクラスからVC出力を変更する方法はありますか?

  1. シングルトン クラス NSURLConnection がすべての通信を処理しています。簡単な電子メールの変更から、トランザクション テーブルの更新まで、あらゆることを行います。これは私には間違っているように思われ、誰が何を呼び出しているかを追跡するのが非常に難しくなります。繰り返しますが、私は MVC の私の解釈に従っていきます。すべての VC に NSURLConnection を用意し、それらのクラスで何らかの処理を行う方がはるかに簡単だと思います。ただし、それは MVC(ish) ではありません。

  2. すべての VC に値を割り当てるために使用するシングルトン クラスには、100 近くの変数、配列などがあります。これも私には間違っているように思えますが、他の方法は考えられません。

4

5 に答える 5

3

NSURLConnection デリゲート (connectionDidFinishLoading) で、どの URL 呼び出しが行われているかをどのように区別できますか?

各デリゲート メソッド ( など-connectionDidFinishLoading:) には、connectionどの接続がメッセージを送信したかを示すパラメーターがあります。特定の接続は、一度に 1 つの URL しかロードできないため、URL と接続の間には 1 対 1 の対応があります。

ダウンロードが完了したときに、「connectionDidFinishLoading」以外でどのように通知できますか?

そのメソッド、接続がいつ終了するかを通知します。アプリにとって役立つ場所にその情報を保存するのは、あなた次第です。

更新:追加した内容に基づいて、「処理」クラスがアプリのモデルになります。アプリの残りの部分は、各トランザクションにサーバーへのメッセージが含まれていることを気にする必要はありません。それはモデルの仕事だけです。また、モデルが (シングルトンは言うまでもなく) 単一のオブジェクトでなければならない理由はありません。一緒に機能するオブジェクトのグループにすることができます。

したがって、アプリケーションのモデルへのインターフェイスを表すクラス (プロセッサと呼びましょう) がある場合があります (これを「モデル コントローラ」と呼ぶ人もいます)。Processor のインスタンスは、アプリの現在のローカル状態を格納するためのローカル データベースを作成する場合があります。また、サーバーとの単一のトランザクションを表す Transaction クラスを使用する場合もあります。トランザクションは、リクエストを作成し、それをサーバーに送信し、レスポンスを取得し、データベースを更新し、トランザクションが完了したことをプロセッサに伝えることができます。または、アプリの他の部分 (View Controller の 1 つなど) が Processor に新しいトランザクションを処理するように要求した場合、Processor は要求元のオブジェクトを作成したトランザクションに渡し、トランザクションがリクエスターを直接更新できるようにします。

アプリをどこで使用する予定なのかを知らずに、アプリの最適な計画を判断するのは困難ですが、通常のガイドラインは次のとおりです。

  • 問題を解決しやすい部分に分割する

  • 各クラスの責任の範囲を制限する

  • 何かが複雑に見える場合は、おそらく

モデルをいくつかのクラスに分割すると、テストも簡単になります。Transaction クラスの一連の単体テストを作成するのがいかに簡単か想像できるでしょう。同じことがプロセッサにも当てはまります。サーバー トランザクションが別のクラスにある場合、プロセッサが正しいことを行っていることをテストする方が簡単です。

于 2012-06-04T18:31:35.390 に答える
1

これがお役に立てば幸いです。

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{   
    NSString *urlString = [[[connection originalRequest] URL] absoluteString];
    if ([urlString caseInsensitiveCompare:@"http://www.apple.com"] == NSOrderedSame) {
        //Do Task#1
    }
    else if ([urlString caseInsensitiveCompare:@"http://www.google.com"] == NSOrderedSame)
    {
        //Do Task#2
    }
}
于 2012-06-04T19:08:17.953 に答える
1

同じデリゲートに対して複数の NSURLConnections がある場合は、どの NSURLConnection が呼び出されているかに応じてデータを格納する、グローバル (インスタンス変数としましょう) NSMutableDictionary インスタンスの使用を検討してください。たとえば、接続のメモリ内アドレスを NSString に変換して使用できます (次のようなもの)。

[NSString stringWithFormat:@"%p", connection]

トリックを行う必要があります)。

また、メソッドconnectionDidFinishLoading:connection:didFailLoadWithError:メソッドで、NSURLConnections に対応するキーを削除します。したがって、接続が終了したかどうかを「外部」から知ることができます。それが辞書にあるかどうかを確認するだけです。

于 2012-06-04T18:30:10.930 に答える
1

NSURLConnection をサブクラス化することをお勧めします。NSIntegertagと BOOLの 2 つのプロパティを追加するだけisFinishedです。このように#defineして、異なるリクエストごとにタグを付け、デリゲート メソッドでタグで識別できます。では、BOOL を YES にconnectionDidFinishLoading設定し、isFinished接続が完了した場合に他の方法でチェックインできます。


これが私自身の NSURLConnection サブクラス、TTURLConnection です。

TTURLConnection.h:

#import <Foundation/Foundation.h>

@interface TTURLConnection : NSURLConnection <NSURLConnectionDelegate>

@property (nonatomic) NSInteger tag;
@property (nonatomic) BOOL isLocked;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam;

@end

TTURLConnection.m:

#import "TTURLConnection.h"

@implementation TTURLConnection

@synthesize tag;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam {
    self = [super initWithRequest:request delegate:delegate 
        startImmediately:startImmediately];

    if(self) {
        self.tag = tagParam;
    }

    return self;
}

@end
于 2012-06-04T18:55:20.660 に答える
1

ネットワーク接続経由​​でデータをダウンロードする場合は、ASIHttpRequestを使用することをお勧めします。これにより、ファイルを非同期でダウンロードできるようになります。つまり、ダウンロード プロセス中にインターフェイスがフリーズすることはありません。

を使用する場合はASIHttpRequest、 を設定することもできますdidFinishSelector。これにより、特定の URL の読み込みが完了したときに呼び出されるメソッドを制御できます。

これを見てください:

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

[request setDelegate:self];
[request startAsynchronous];
[request setDidFinishSelector:@selector(requestDone:)];

それで:

- (void)requestDone:(ASIHTTPRequest *)request
{
   // Use when fetching text data
   NSString *responseString = [request responseString];

   // Use when fetching binary data
   NSData *responseData = [request responseData];

   // If you want, you can get the url of the request like this
   NSURL *url = [request url];
}

質問の 2 番目の部分については、requestDone:メソッドが呼び出されていない場合、ダウンロードが完了していないことがわかります。

複数のダウンロードでより複雑なことをしたい場合は、ASIHttpRequestキュー機能も提供します。ここを見てください。

于 2012-06-04T18:39:45.940 に答える