10

2 か月前、私は新しい iPhone アプリケーションの作成を開始しました。このため、ユーザー認証、ユーザー プロファイル、フレンドシップ システム、メディア処理、メッセージングなどの必要な機能を多数持つことができる、一般的な RESTFul Web サービスを作成しました。システムなど。私の考えでは、将来の iPhone アプリケーションでこの Web サービスを再利用するユースケースがいくつかあります。

このような心構えで、メディア (画像、ビデオ、サウンド) のセットアップと処理、Web サービスとの通信、解析とマッピングなどのすべての重労働を処理する、このアプリケーション (および将来のすべてのアプリケーション) 用の静的ライブラリを作成することにしました。結果の処理、CoreData の処理など。

私のアプリケーションでは、多くの並列タスクが実行されているシナリオがあります (最悪の場合)。たとえば、ユーザーが現在自分のプロフィール写真を変更しているときに、アプリケーションがユーザーの場所を (バックグラウンドで) サーバーに送信し、新しいプッシュ通知が送信されます。受け取った。

そこで、各論理操作 (SendUserLocation や GetCurrentFriendList など) を NSOperation にカプセル化し、それらを serviceQueue (NSOperationQueue) に追加することにしました。

各操作は、操作が Web サービスから結果を正常に取得し、すぐに処理する必要がある場合にサブタスクを生成できます。

代替テキスト

典型的な ServiceManager メソッドは次のようになります

- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector {
    ELOSyncFriends *opSyncFriends  = [[ELOSyncFriends alloc] initWithSM:self];
    [self ELServiceLogger:opSyncFriends];
    [serviceQueue addOperation:opSyncFriends];
    if(observer) {
        [self registerObserver:observer selector:selector name:opSyncFriends.notificationName]; 
    }
}

各操作、(サーバーへの) 要求、および subTask は、GUID を notificationName として使用して、処理が完了したときに親オブジェクトに通知します。操作のすべてが完了すると、ユーザー インターフェイスに通知が返されます。

とはいえ、サブタスクを追加および削除するためのコードは次のようになります

- (void)removeSubTask:(NSNotification*)notification {
    ELRequest *request = (ELRequest*)[notification object];
    [subTasks removeObjectIdenticalTo:request.notificationName];
    if([subTasks count] == 0) {
         // all SubTaks done, send notification to parent
        [serviceManager.notificationCenter postNotificationName:self.notificationName object:request];
    }
}

- (NSString*)addSubTask {
    NSString* newName = [self GetUUID];
    [subTasks addObject:[newName retain]];
    [serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil];
    return newName;
} 

- (NSString *)GetUUID {
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

あとは、GUI で serviceManager を呼び出して、次のような特定の操作を開始するだけです。

[self.core.serviceManager activateFriendsSync:nil onSuccess:nil];

オブザーバーを登録したい場合は、次のようにオブザーバー オブジェクトとセレクターを渡すだけです。

[self.core.serviceManager activateFriendsSync:self onSuccess:@selector(myMethod:)];

最後になりましたが、私の質問: 「アーキテクチャ」は非常にうまく動作し、安定していますが、実行する価値はありますか? オーバーヘッドが多すぎますか? それは理にかなっていますか?個人的には、並行操作をどのように実装していますか?

ベスト・ヘンリック

PS私の質問を自由に編集し、質問をして(コメントとして)、この考えの名前を呼んでください。

基本的に私は英語のネイティブスピーカーではないので、説明するのに本当に苦労しました. 誤解しないでください。私は、この投稿を何らかの形で自慢するために書いたわけではありません。私がしたいのは学ぶことだけです(そして、より高度なiPhone / Objective Cの質問を書くことかもしれません)

4

3 に答える 3

4

はい、それがサービス リクエストに割り当てられていて、多くの呼び出しを行う必要がある場合、そのようなライブラリは (imo) やり過ぎではなく、似たようなものを書いています。この構造により、非常に複雑で多様なタスクを伴う複雑なシステムの管理が非常に簡単になりました。

私が行った主な設計上の違いは、サービス マネージャーで NSNotification を使用しなかったことです。代わりに、コールバックにプロトコル/タイプを使用することを好みました(操作が参照を保持します)。NSNotification は非常に重いです。この場合、操作はリスナー/通知されたオブジェクトを保持しませんが、リスナーは操作を保持します。関係が 1-1 の場合、キャンセルを許可します。

もう 1 つの重要な考慮事項は、早い段階でスレッド化を定義することです。クライアントが応答を受け取るスレッドを定義できるようにします。この理由は、通知された/リスナーが UI を更新する必要がある場合 (たとえば、UIKit または AppKit を使用している場合)、コールバックの制約または論理エントリがしばしば存在するためです。したがって、作成者は操作に対して「メイン スレッドから通知する必要があります」または「任意のスレッドからの応答を処理できます」と言うことができます。これにより、コントローラー/リスナー/オブザーバーのコードとエラーの可能性が大幅に減少します。

于 2011-02-15T20:21:57.817 に答える
2

「サブオペレーション」の場合:親オペレーションが各子オペレーションの依存関係( cf.-[ NSOperation addDependency: ] )である場合、それらをキューに入れるのはどうですか?NSOperationQueueは、操作の山全体を順番に並べることができます。これは簡単で自然な作業だと思います。

于 2012-09-07T01:51:41.917 に答える
1

あなたは、私がいくつかのアプリで使用している非常によく似たアーキテクチャについて説明しました:)

サービスマネージャーレイヤーがオブジェクトのセットを即座に返し、しばらくすると更新されたセットを返します。

NSArray *stuff = [serviceManager getFriendsForUser:@"Bob"];

そして、サーバーが応答した後、更新されたリスト (この場合はボブの友達) を含む NSNotification が受信されます。

この小さな変更を除けば、アーキテクチャは同じです!

すべてをセットアップするのは大変な作業ですが、バグの修正やコードの拡張がはるかに簡単になるため、長い目で見れば価値があると思います。

于 2010-10-04T16:27:13.153 に答える